Skip to content

Commit 4cef295

Browse files
committed
Improve loading for Users
1 parent a629a70 commit 4cef295

File tree

6 files changed

+128
-105
lines changed

6 files changed

+128
-105
lines changed

site/src/components/Loader/FullScreenLoader.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import CircularProgress from "@material-ui/core/CircularProgress"
22
import { makeStyles } from "@material-ui/core/styles"
33
import React from "react"
44

5-
export const useStyles = makeStyles(() => ({
5+
export const useStyles = makeStyles((theme) => ({
66
root: {
77
position: "absolute",
88
top: "0",
@@ -12,6 +12,7 @@ export const useStyles = makeStyles(() => ({
1212
display: "flex",
1313
justifyContent: "center",
1414
alignItems: "center",
15+
background: theme.palette.background.default,
1516
},
1617
}))
1718

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import CircularProgress from "@material-ui/core/CircularProgress"
2+
import { makeStyles } from "@material-ui/core/styles"
3+
import TableCell from "@material-ui/core/TableCell"
4+
import TableRow from "@material-ui/core/TableRow"
5+
import React from "react"
6+
7+
export const TableLoader: React.FC = () => {
8+
const styles = useStyles()
9+
10+
return (
11+
<TableRow>
12+
<TableCell colSpan={999} className={styles.cell}>
13+
<CircularProgress size={30} />
14+
</TableCell>
15+
</TableRow>
16+
)
17+
}
18+
19+
const useStyles = makeStyles((theme) => ({
20+
cell: {
21+
textAlign: "center",
22+
height: theme.spacing(20),
23+
},
24+
}))

site/src/components/UsersTable/UsersTable.tsx

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import * as TypesGen from "../../api/typesGenerated"
99
import { EmptyState } from "../EmptyState/EmptyState"
1010
import { RoleSelect } from "../RoleSelect/RoleSelect"
1111
import { TableHeaderRow } from "../TableHeaders/TableHeaders"
12+
import { TableLoader } from "../TableLoader/TableLoader"
1213
import { TableRowMenu } from "../TableRowMenu/TableRowMenu"
1314
import { TableTitle } from "../TableTitle/TableTitle"
1415
import { UserCell } from "../UserCell/UserCell"
@@ -24,12 +25,12 @@ export const Language = {
2425
}
2526

2627
export interface UsersTableProps {
27-
users: TypesGen.User[]
28+
users?: TypesGen.User[]
29+
roles?: TypesGen.Role[]
30+
isUpdatingUserRoles?: boolean
2831
onSuspendUser: (user: TypesGen.User) => void
2932
onResetUserPassword: (user: TypesGen.User) => void
3033
onUpdateUserRoles: (user: TypesGen.User, roles: TypesGen.Role["name"][]) => void
31-
roles: TypesGen.Role[]
32-
isUpdatingUserRoles?: boolean
3334
}
3435

3536
export const UsersTable: React.FC<UsersTableProps> = ({
@@ -40,6 +41,8 @@ export const UsersTable: React.FC<UsersTableProps> = ({
4041
onUpdateUserRoles,
4142
isUpdatingUserRoles,
4243
}) => {
44+
const isLoading = !users || !roles
45+
4346
return (
4447
<Table>
4548
<TableHead>
@@ -52,38 +55,41 @@ export const UsersTable: React.FC<UsersTableProps> = ({
5255
</TableHeaderRow>
5356
</TableHead>
5457
<TableBody>
55-
{users.map((u) => (
56-
<TableRow key={u.id}>
57-
<TableCell>
58-
<UserCell Avatar={{ username: u.username }} primaryText={u.username} caption={u.email} />{" "}
59-
</TableCell>
60-
<TableCell>
61-
<RoleSelect
62-
roles={roles}
63-
selectedRoles={u.roles}
64-
loading={isUpdatingUserRoles}
65-
onChange={(roles) => onUpdateUserRoles(u, roles)}
66-
/>
67-
</TableCell>
68-
<TableCell>
69-
<TableRowMenu
70-
data={u}
71-
menuItems={[
72-
{
73-
label: Language.suspendMenuItem,
74-
onClick: onSuspendUser,
75-
},
76-
{
77-
label: Language.resetPasswordMenuItem,
78-
onClick: onResetUserPassword,
79-
},
80-
]}
81-
/>
82-
</TableCell>
83-
</TableRow>
84-
))}
58+
{isLoading && <TableLoader />}
59+
{users &&
60+
roles &&
61+
users.map((u) => (
62+
<TableRow key={u.id}>
63+
<TableCell>
64+
<UserCell Avatar={{ username: u.username }} primaryText={u.username} caption={u.email} />{" "}
65+
</TableCell>
66+
<TableCell>
67+
<RoleSelect
68+
roles={roles}
69+
selectedRoles={u.roles}
70+
loading={isUpdatingUserRoles}
71+
onChange={(roles) => onUpdateUserRoles(u, roles)}
72+
/>
73+
</TableCell>
74+
<TableCell>
75+
<TableRowMenu
76+
data={u}
77+
menuItems={[
78+
{
79+
label: Language.suspendMenuItem,
80+
onClick: onSuspendUser,
81+
},
82+
{
83+
label: Language.resetPasswordMenuItem,
84+
onClick: onResetUserPassword,
85+
},
86+
]}
87+
/>
88+
</TableCell>
89+
</TableRow>
90+
))}
8591

86-
{users.length === 0 && (
92+
{users && users.length === 0 && (
8793
<TableRow>
8894
<TableCell colSpan={999}>
8995
<Box p={4}>

site/src/pages/UsersPage/UsersPage.tsx

Lines changed: 57 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { useActor } from "@xstate/react"
22
import React, { useContext, useEffect } from "react"
33
import { useNavigate } from "react-router"
44
import { ConfirmDialog } from "../../components/ConfirmDialog/ConfirmDialog"
5-
import { FullScreenLoader } from "../../components/Loader/FullScreenLoader"
65
import { ResetPasswordDialog } from "../../components/ResetPasswordDialog/ResetPasswordDialog"
76
import { XServiceContext } from "../../xServices/StateContext"
87
import { UsersPageView } from "./UsersPageView"
@@ -46,67 +45,63 @@ export const UsersPage: React.FC = () => {
4645
usersSend("GET_USERS")
4746
}, [usersSend])
4847

49-
if (!users || !roles) {
50-
return <FullScreenLoader />
51-
} else {
52-
return (
53-
<>
54-
<UsersPageView
55-
roles={roles}
56-
users={users}
57-
openUserCreationDialog={() => {
58-
navigate("/users/create")
59-
}}
60-
onSuspendUser={(user) => {
61-
usersSend({ type: "SUSPEND_USER", userId: user.id })
62-
}}
63-
onResetUserPassword={(user) => {
64-
usersSend({ type: "RESET_USER_PASSWORD", userId: user.id })
65-
}}
66-
onUpdateUserRoles={(user, roles) => {
67-
usersSend({
68-
type: "UPDATE_USER_ROLES",
69-
userId: user.id,
70-
roles,
71-
})
72-
}}
73-
error={getUsersError}
74-
isUpdatingUserRoles={usersState.matches("updatingUserRoles")}
75-
/>
48+
return (
49+
<>
50+
<UsersPageView
51+
roles={roles}
52+
users={users}
53+
openUserCreationDialog={() => {
54+
navigate("/users/create")
55+
}}
56+
onSuspendUser={(user) => {
57+
usersSend({ type: "SUSPEND_USER", userId: user.id })
58+
}}
59+
onResetUserPassword={(user) => {
60+
usersSend({ type: "RESET_USER_PASSWORD", userId: user.id })
61+
}}
62+
onUpdateUserRoles={(user, roles) => {
63+
usersSend({
64+
type: "UPDATE_USER_ROLES",
65+
userId: user.id,
66+
roles,
67+
})
68+
}}
69+
error={getUsersError}
70+
isUpdatingUserRoles={usersState.matches("updatingUserRoles")}
71+
/>
7672

77-
<ConfirmDialog
78-
type="delete"
79-
hideCancel={false}
80-
open={usersState.matches("confirmUserSuspension")}
81-
confirmLoading={usersState.matches("suspendingUser")}
82-
title={Language.suspendDialogTitle}
83-
confirmText={Language.suspendDialogAction}
84-
onConfirm={() => {
85-
usersSend("CONFIRM_USER_SUSPENSION")
86-
}}
87-
onClose={() => {
88-
usersSend("CANCEL_USER_SUSPENSION")
89-
}}
90-
description={
91-
<>
92-
{Language.suspendDialogMessagePrefix} <strong>{userToBeSuspended?.username}</strong>?
93-
</>
94-
}
95-
/>
73+
<ConfirmDialog
74+
type="delete"
75+
hideCancel={false}
76+
open={usersState.matches("confirmUserSuspension")}
77+
confirmLoading={usersState.matches("suspendingUser")}
78+
title={Language.suspendDialogTitle}
79+
confirmText={Language.suspendDialogAction}
80+
onConfirm={() => {
81+
usersSend("CONFIRM_USER_SUSPENSION")
82+
}}
83+
onClose={() => {
84+
usersSend("CANCEL_USER_SUSPENSION")
85+
}}
86+
description={
87+
<>
88+
{Language.suspendDialogMessagePrefix} <strong>{userToBeSuspended?.username}</strong>?
89+
</>
90+
}
91+
/>
9692

97-
<ResetPasswordDialog
98-
loading={usersState.matches("resettingUserPassword")}
99-
user={userToResetPassword}
100-
newPassword={newUserPassword}
101-
open={usersState.matches("confirmUserPasswordReset")}
102-
onClose={() => {
103-
usersSend("CANCEL_USER_PASSWORD_RESET")
104-
}}
105-
onConfirm={() => {
106-
usersSend("CONFIRM_USER_PASSWORD_RESET")
107-
}}
108-
/>
109-
</>
110-
)
111-
}
93+
<ResetPasswordDialog
94+
loading={usersState.matches("resettingUserPassword")}
95+
user={userToResetPassword}
96+
newPassword={newUserPassword}
97+
open={usersState.matches("confirmUserPasswordReset")}
98+
onClose={() => {
99+
usersSend("CANCEL_USER_PASSWORD_RESET")
100+
}}
101+
onConfirm={() => {
102+
usersSend("CONFIRM_USER_PASSWORD_RESET")
103+
}}
104+
/>
105+
</>
106+
)
112107
}

site/src/pages/UsersPage/UsersPageView.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ export const Language = {
1212
}
1313

1414
export interface UsersPageViewProps {
15-
users: TypesGen.User[]
15+
users?: TypesGen.User[]
16+
roles?: TypesGen.Role[]
17+
error?: unknown
18+
isUpdatingUserRoles?: boolean
1619
openUserCreationDialog: () => void
1720
onSuspendUser: (user: TypesGen.User) => void
1821
onResetUserPassword: (user: TypesGen.User) => void
1922
onUpdateUserRoles: (user: TypesGen.User, roles: TypesGen.Role["name"][]) => void
20-
roles: TypesGen.Role[]
21-
error?: unknown
22-
isUpdatingUserRoles?: boolean
2323
}
2424

2525
export const UsersPageView: React.FC<UsersPageViewProps> = ({
@@ -41,10 +41,10 @@ export const UsersPageView: React.FC<UsersPageViewProps> = ({
4141
) : (
4242
<UsersTable
4343
users={users}
44+
roles={roles}
4445
onSuspendUser={onSuspendUser}
4546
onResetUserPassword={onResetUserPassword}
4647
onUpdateUserRoles={onUpdateUserRoles}
47-
roles={roles}
4848
isUpdatingUserRoles={isUpdatingUserRoles}
4949
/>
5050
)}

site/src/xServices/users/usersXService.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,6 @@ export const usersMachine = createMachine(
7373
},
7474
id: "usersState",
7575
initial: "idle",
76-
context: {
77-
users: [],
78-
},
7976
states: {
8077
idle: {
8178
on: {

0 commit comments

Comments
 (0)