1- import { User } from '@luna/contexts/api/auth/types' ;
1+ import { Role , User } from '@luna/contexts/api/auth/types' ;
22import { UserAddModal } from '@luna/modals/UserAddModal' ;
33import { UserDeleteModal } from '@luna/modals/UserDeleteModal' ;
44import { UserDetailsModal } from '@luna/modals/UserDetailsModal' ;
@@ -9,6 +9,11 @@ import { HomeContent } from '@luna/screens/home/HomeContent';
99import { getOrThrow } from '@luna/utils/result' ;
1010import {
1111 Button ,
12+ Chip ,
13+ Dropdown ,
14+ DropdownItem ,
15+ DropdownMenu ,
16+ DropdownTrigger ,
1217 Spinner ,
1318 Table ,
1419 TableBody ,
@@ -22,6 +27,7 @@ import { useAsyncList } from '@react-stately/data';
2227import {
2328 IconEye ,
2429 IconPencil ,
30+ IconPlus ,
2531 IconTrash ,
2632 IconUserPlus ,
2733} from '@tabler/icons-react' ;
@@ -81,6 +87,20 @@ export function UsersView() {
8187 const [ showUserDeleteModal , setShowUserDeleteModal ] = useState ( false ) ;
8288 const [ userId , setUserId ] = useState ( 0 ) ;
8389
90+ const [ allRoles , setAllRoles ] = useState < Role [ ] > ( [ ] ) ;
91+
92+ useEffect ( ( ) => {
93+ const fetchRoles = async ( ) => {
94+ const rolesResult = await auth . getAllRoles ( ) ;
95+ if ( rolesResult . ok ) {
96+ setAllRoles ( rolesResult . value ) ;
97+ } else {
98+ console . log ( 'Could not get roles:' , rolesResult . error ) ;
99+ }
100+ } ;
101+ fetchRoles ( ) ;
102+ } , [ auth ] ) ;
103+
84104 return (
85105 // TODO: Lazy rendering
86106 < HomeContent
@@ -148,6 +168,9 @@ export function UsersView() {
148168 < TableColumn key = "lastSeen" allowsSorting >
149169 Last Seen
150170 </ TableColumn >
171+ < TableColumn key = "roles" allowsSorting >
172+ Roles
173+ </ TableColumn >
151174 < TableColumn key = "actions" > Actions</ TableColumn >
152175 </ TableHeader >
153176 < TableBody items = { users . items } isLoading = { isLoading } >
@@ -159,6 +182,69 @@ export function UsersView() {
159182 < TableCell > { user . createdAt . toLocaleString ( ) } </ TableCell >
160183 < TableCell > { user . updatedAt . toLocaleString ( ) } </ TableCell >
161184 < TableCell > { user . lastSeen . toLocaleString ( ) } </ TableCell >
185+ < TableCell >
186+ { user . roles . map ( role => (
187+ < Chip
188+ key = { role . id }
189+ onClose = { async ( ) => {
190+ console . log (
191+ 'removing user' ,
192+ user . username ,
193+ 'from role' ,
194+ role . name
195+ ) ;
196+ const result = await auth . removeUserFromRole (
197+ user . id ,
198+ role . id
199+ ) ;
200+ if ( ! result . ok ) {
201+ console . log ( result . error ) ;
202+ return ;
203+ }
204+ users . reload ( ) ;
205+ } }
206+ className = "m-1 hover:bg-danger"
207+ >
208+ { role . name }
209+ </ Chip >
210+ ) ) }
211+ < Dropdown >
212+ < DropdownTrigger >
213+ < Chip
214+ color = "success"
215+ className = "p-0 hover:cursor-pointer"
216+ variant = "bordered"
217+ >
218+ < IconPlus size = "15px" />
219+ </ Chip >
220+ </ DropdownTrigger >
221+ < DropdownMenu
222+ items = { allRoles . filter (
223+ role =>
224+ undefined === user . roles . find ( r => r . id === role . id )
225+ ) }
226+ onAction = { async key => {
227+ console . log ( 'adding user' , user . username , 'to role' , key ) ;
228+ const roleid : number = parseInt ( key . toString ( ) ) ;
229+ const result = await auth . addUserToRole ( user . id , roleid ) ;
230+ if ( ! result . ok ) {
231+ console . log ( result . error ) ;
232+ return ;
233+ }
234+ users . reload ( ) ;
235+ } }
236+ >
237+ { ( role : Role ) => (
238+ < DropdownItem
239+ key = { role . id }
240+ className = "data-[hover=true]:bg-success"
241+ >
242+ { role . name }
243+ </ DropdownItem >
244+ ) }
245+ </ DropdownMenu >
246+ </ Dropdown >
247+ </ TableCell >
162248 < TableCell >
163249 < div className = "relative flex items-center gap-2" >
164250 < Tooltip content = "Details" >
0 commit comments