@@ -2,8 +2,10 @@ import Box from "@material-ui/core/Box"
22import { makeStyles } from "@material-ui/core/styles"
33import TableCell from "@material-ui/core/TableCell"
44import TableRow from "@material-ui/core/TableRow"
5+ import { ChooseOne , Cond } from "components/Conditionals/ChooseOne"
56import { LastUsed } from "components/LastUsed/LastUsed"
67import { FC } from "react"
8+ import { useTranslation } from "react-i18next"
79import * as TypesGen from "../../api/typesGenerated"
810import { combineClasses } from "../../util/combineClasses"
911import { AvatarData } from "../AvatarData/AvatarData"
@@ -12,15 +14,6 @@ import { RoleSelect } from "../RoleSelect/RoleSelect"
1214import { TableLoader } from "../TableLoader/TableLoader"
1315import { TableRowMenu } from "../TableRowMenu/TableRowMenu"
1416
15- export const Language = {
16- emptyMessage : "No users found" ,
17- suspendMenuItem : "Suspend" ,
18- deleteMenuItem : "Delete" ,
19- listWorkspacesMenuItem : "View workspaces" ,
20- activateMenuItem : "Activate" ,
21- resetPasswordMenuItem : "Reset password" ,
22- }
23-
2417interface UsersTableBodyProps {
2518 users ?: TypesGen . User [ ]
2619 roles ?: TypesGen . AssignableRoles [ ]
@@ -36,6 +29,7 @@ interface UsersTableBodyProps {
3629 user : TypesGen . User ,
3730 roles : TypesGen . Role [ "name" ] [ ] ,
3831 ) => void
32+ isNonInitialPage : boolean
3933}
4034
4135export const UsersTableBody : FC <
@@ -52,121 +46,144 @@ export const UsersTableBody: FC<
5246 isUpdatingUserRoles,
5347 canEditUsers,
5448 isLoading,
49+ isNonInitialPage,
5550} ) => {
5651 const styles = useStyles ( )
57-
58- if ( isLoading ) {
59- return < TableLoader />
60- }
61-
62- if ( ! users || users . length === 0 ) {
63- return (
64- < TableRow >
65- < TableCell colSpan = { 999 } >
66- < Box p = { 4 } >
67- < EmptyState message = { Language . emptyMessage } />
68- </ Box >
69- </ TableCell >
70- </ TableRow >
71- )
72- }
52+ const { t } = useTranslation ( "usersPage" )
7353
7454 return (
75- < >
76- { users . map ( ( user ) => {
77- // When the user has no role we want to show they are a Member
78- const fallbackRole : TypesGen . Role = {
79- name : "member" ,
80- display_name : "Member" ,
81- }
82- const userRoles = user . roles . length === 0 ? [ fallbackRole ] : user . roles
55+ < ChooseOne >
56+ < Cond condition = { Boolean ( isLoading ) } >
57+ < TableLoader />
58+ </ Cond >
59+ < Cond condition = { ! users || users . length === 0 } >
60+ < ChooseOne >
61+ < Cond condition = { isNonInitialPage } >
62+ < TableRow >
63+ < TableCell colSpan = { 999 } >
64+ < Box p = { 4 } >
65+ < EmptyState message = { t ( "emptyPageMessage" ) } />
66+ </ Box >
67+ </ TableCell >
68+ </ TableRow >
69+ </ Cond >
70+ < Cond >
71+ < TableRow >
72+ < TableCell colSpan = { 999 } >
73+ < Box p = { 4 } >
74+ < EmptyState message = { t ( "emptyMessage" ) } />
75+ </ Box >
76+ </ TableCell >
77+ </ TableRow >
78+ </ Cond >
79+ </ ChooseOne >
80+ </ Cond >
81+ < Cond >
82+ < >
83+ { users &&
84+ users . map ( ( user ) => {
85+ // When the user has no role we want to show they are a Member
86+ const fallbackRole : TypesGen . Role = {
87+ name : "member" ,
88+ display_name : "Member" ,
89+ }
90+ const userRoles =
91+ user . roles . length === 0 ? [ fallbackRole ] : user . roles
8392
84- return (
85- < TableRow key = { user . id } >
86- < TableCell >
87- < AvatarData
88- title = { user . username }
89- subtitle = { user . email }
90- highlightTitle
91- avatar = {
92- user . avatar_url ? (
93- < img
94- className = { styles . avatar }
95- alt = { `${ user . username } 's Avatar` }
96- src = { user . avatar_url }
93+ return (
94+ < TableRow key = { user . id } >
95+ < TableCell >
96+ < AvatarData
97+ title = { user . username }
98+ subtitle = { user . email }
99+ highlightTitle
100+ avatar = {
101+ user . avatar_url ? (
102+ < img
103+ className = { styles . avatar }
104+ alt = { `${ user . username } 's Avatar` }
105+ src = { user . avatar_url }
106+ />
107+ ) : null
108+ }
97109 />
98- ) : null
99- }
100- />
101- </ TableCell >
102- < TableCell
103- className = { combineClasses ( [
104- styles . status ,
105- user . status === "suspended" ? styles . suspended : undefined ,
106- ] ) }
107- >
108- { user . status }
109- </ TableCell >
110- < TableCell >
111- < LastUsed lastUsedAt = { user . last_seen_at } />
112- </ TableCell >
113- < TableCell >
114- { canEditUsers ? (
115- < RoleSelect
116- roles = { roles ?? [ ] }
117- selectedRoles = { userRoles }
118- loading = { isUpdatingUserRoles }
119- onChange = { ( roles ) => {
120- // Remove the fallback role because it is only for the UI
121- roles = roles . filter ( ( role ) => role !== fallbackRole . name )
122- onUpdateUserRoles ( user , roles )
123- } }
124- />
125- ) : (
126- < > { userRoles . map ( ( role ) => role . display_name ) . join ( ", " ) } </ >
127- ) }
128- </ TableCell >
129- { canEditUsers && (
130- < TableCell >
131- < TableRowMenu
132- data = { user }
133- menuItems = {
134- // Return either suspend or activate depending on status
135- ( user . status === "active"
136- ? [
137- {
138- label : Language . suspendMenuItem ,
139- onClick : onSuspendUser ,
140- } ,
141- ]
142- : [
143- {
144- label : Language . activateMenuItem ,
145- onClick : onActivateUser ,
146- } ,
147- ]
148- ) . concat (
149- {
150- label : Language . deleteMenuItem ,
151- onClick : onDeleteUser ,
152- } ,
153- {
154- label : Language . listWorkspacesMenuItem ,
155- onClick : onListWorkspaces ,
156- } ,
157- {
158- label : Language . resetPasswordMenuItem ,
159- onClick : onResetUserPassword ,
160- } ,
161- )
162- }
163- />
164- </ TableCell >
165- ) }
166- </ TableRow >
167- )
168- } ) }
169- </ >
110+ </ TableCell >
111+ < TableCell
112+ className = { combineClasses ( [
113+ styles . status ,
114+ user . status === "suspended"
115+ ? styles . suspended
116+ : undefined ,
117+ ] ) }
118+ >
119+ { user . status }
120+ </ TableCell >
121+ < TableCell >
122+ < LastUsed lastUsedAt = { user . last_seen_at } />
123+ </ TableCell >
124+ < TableCell >
125+ { canEditUsers ? (
126+ < RoleSelect
127+ roles = { roles ?? [ ] }
128+ selectedRoles = { userRoles }
129+ loading = { isUpdatingUserRoles }
130+ onChange = { ( roles ) => {
131+ // Remove the fallback role because it is only for the UI
132+ roles = roles . filter (
133+ ( role ) => role !== fallbackRole . name ,
134+ )
135+ onUpdateUserRoles ( user , roles )
136+ } }
137+ />
138+ ) : (
139+ < >
140+ { userRoles . map ( ( role ) => role . display_name ) . join ( ", " ) }
141+ </ >
142+ ) }
143+ </ TableCell >
144+ { canEditUsers && (
145+ < TableCell >
146+ < TableRowMenu
147+ data = { user }
148+ menuItems = {
149+ // Return either suspend or activate depending on status
150+ ( user . status === "active"
151+ ? [
152+ {
153+ label : t ( "suspendMenuItem" ) ,
154+ onClick : onSuspendUser ,
155+ } ,
156+ ]
157+ : [
158+ {
159+ label : t ( "activateMenuItem" ) ,
160+ onClick : onActivateUser ,
161+ } ,
162+ ]
163+ ) . concat (
164+ {
165+ label : t ( "deleteMenuItem" ) ,
166+ onClick : onDeleteUser ,
167+ } ,
168+ {
169+ label : t ( "listWorkspacesMenuItem" ) ,
170+ onClick : onListWorkspaces ,
171+ } ,
172+ {
173+ label : t ( "resetPasswordMenuItem" ) ,
174+ onClick : onResetUserPassword ,
175+ } ,
176+ )
177+ }
178+ />
179+ </ TableCell >
180+ ) }
181+ </ TableRow >
182+ )
183+ } ) }
184+ </ >
185+ </ Cond >
186+ </ ChooseOne >
170187 )
171188}
172189
0 commit comments