@@ -6,9 +6,17 @@ import PrincipalRolesList, {PrincipalRoleItem, PrincipalItem} from "@/app/ui/pri
66import Grants , { Grant } from "@/app/ui/grants"
77import CreateCatalogModal from "@/app/ui/create-catalog-modal"
88import CreateCatalogRoleModal from "@/app/ui/create-catalog-role-modal"
9+ import AssignCatalogRoleModal from "@/app/ui/assign-catalog-role-modal"
10+ import RemoveCatalogRoleModal from "@/app/ui/remove-catalog-role-modal"
911import { useCallback , useEffect , useState } from 'react'
10- import { Breadcrumb , Button , Divider , Flex , message , Space , Spin , Typography } from 'antd' ;
11- import { FolderAddOutlined , FolderOpenOutlined , UsergroupAddOutlined } from '@ant-design/icons' ;
12+ import { Breadcrumb , Button , Divider , message , Space , Spin , Typography , Flex } from 'antd' ;
13+ import {
14+ FolderAddOutlined ,
15+ FolderOpenOutlined ,
16+ MinusOutlined ,
17+ PlusOutlined ,
18+ UsergroupAddOutlined
19+ } from '@ant-design/icons' ;
1220import { useAuthenticatedFetch } from '@/hooks/useAuthenticatedFetch' ;
1321
1422const { Title} = Typography ;
@@ -39,6 +47,8 @@ export default function Page() {
3947 const [ grantsLoading , setGrantsLoading ] = useState ( false ) ;
4048 const [ createModalVisible , setCreateModalVisible ] = useState ( false ) ;
4149 const [ createCatalogRoleModalVisible , setCreateCatalogRoleModalVisible ] = useState ( false ) ;
50+ const [ assignCatalogRoleModalVisible , setAssignCatalogRoleModalVisible ] = useState ( false ) ;
51+ const [ removeCatalogRoleModalVisible , setRemoveCatalogRoleModalVisible ] = useState ( false ) ;
4252 const { authenticatedFetch} = useAuthenticatedFetch ( ) ;
4353
4454 const getCatalogs = useCallback ( async ( ) : Promise < CatalogEntity [ ] > => {
@@ -260,10 +270,10 @@ export default function Page() {
260270
261271 try {
262272 await authenticatedFetch (
263- `/api/principal-roles/${ encodeURIComponent ( selectedCatalog ) } /${ encodeURIComponent ( selectedCatalogRole ) } /${ encodeURIComponent ( principalRoleName ) } ` ,
264- {
265- method : 'DELETE' ,
266- }
273+ `/api/principal-roles/${ encodeURIComponent ( selectedCatalog ) } /${ encodeURIComponent ( selectedCatalogRole ) } /${ encodeURIComponent ( principalRoleName ) } ` ,
274+ {
275+ method : 'DELETE' ,
276+ }
267277 ) ;
268278
269279 message . success ( `Principal role "${ principalRoleName } " removed from catalog role "${ selectedCatalogRole } " successfully!` ) ;
@@ -280,10 +290,10 @@ export default function Page() {
280290 const handleDeletePrincipal = async ( principalRoleName : string , principalName : string ) => {
281291 try {
282292 await authenticatedFetch (
283- `/api/principal-role-principals/${ encodeURIComponent ( principalRoleName ) } /${ encodeURIComponent ( principalName ) } ` ,
284- {
285- method : 'DELETE' ,
286- }
293+ `/api/principal-role-principals/${ encodeURIComponent ( principalRoleName ) } /${ encodeURIComponent ( principalName ) } ` ,
294+ {
295+ method : 'DELETE' ,
296+ }
287297 ) ;
288298
289299 message . success ( `Principal "${ principalName } " removed from role "${ principalRoleName } " successfully!` ) ;
@@ -366,6 +376,40 @@ export default function Page() {
366376 }
367377 } ;
368378
379+ const handleAddCatalogRole = ( ) => {
380+ setAssignCatalogRoleModalVisible ( true ) ;
381+ } ;
382+
383+ const handleRemoveCatalogRole = ( ) => {
384+ setRemoveCatalogRoleModalVisible ( true ) ;
385+ } ;
386+
387+ const handleAssignCatalogRoleSuccess = async ( ) => {
388+ if ( selectedCatalog && selectedCatalogRole ) {
389+ // Refresh the principal roles list
390+ setPrincipalRolesLoading ( true ) ;
391+ try {
392+ const roles = await getPrincipalRoles ( selectedCatalog , selectedCatalogRole ) ;
393+ setPrincipalRoles ( roles ) ;
394+ } finally {
395+ setPrincipalRolesLoading ( false ) ;
396+ }
397+ }
398+ } ;
399+
400+ const handleRemoveCatalogRoleSuccess = async ( ) => {
401+ if ( selectedCatalog && selectedCatalogRole ) {
402+ // Refresh the principal roles list
403+ setPrincipalRolesLoading ( true ) ;
404+ try {
405+ const roles = await getPrincipalRoles ( selectedCatalog , selectedCatalogRole ) ;
406+ setPrincipalRoles ( roles ) ;
407+ } finally {
408+ setPrincipalRolesLoading ( false ) ;
409+ }
410+ }
411+ } ;
412+
369413 if ( loading ) {
370414 return (
371415 < Spin size = "large" />
@@ -436,6 +480,25 @@ export default function Page() {
436480 { selectedCatalog && selectedCatalogRole && (
437481 < >
438482 < Divider orientation = "left" > Principal Roles Assigned to Catalog Role</ Divider >
483+ < Flex justify = "flex-end" align = "center" style = { { width : '100%' } } >
484+ < Space >
485+ < Button
486+ type = "default"
487+ icon = { < PlusOutlined /> }
488+ onClick = { handleAddCatalogRole }
489+ >
490+ Add Role
491+ </ Button >
492+ < Button
493+ danger
494+ icon = { < MinusOutlined /> }
495+ onClick = { handleRemoveCatalogRole }
496+ disabled = { principalRoles . length === 0 }
497+ >
498+ Remove Role
499+ </ Button >
500+ </ Space >
501+ </ Flex >
439502 < PrincipalRolesList
440503 roles = { principalRoles }
441504 loading = { principalRolesLoading }
@@ -468,6 +531,23 @@ export default function Page() {
468531 onClose = { ( ) => setCreateCatalogRoleModalVisible ( false ) }
469532 onSuccess = { handleCreateCatalogRoleSuccess }
470533 />
534+
535+ < AssignCatalogRoleModal
536+ visible = { assignCatalogRoleModalVisible }
537+ catalogName = { selectedCatalog }
538+ catalogRoleName = { selectedCatalogRole }
539+ onClose = { ( ) => setAssignCatalogRoleModalVisible ( false ) }
540+ onSuccess = { handleAssignCatalogRoleSuccess }
541+ />
542+
543+ < RemoveCatalogRoleModal
544+ visible = { removeCatalogRoleModalVisible }
545+ catalogName = { selectedCatalog }
546+ catalogRoleName = { selectedCatalogRole }
547+ assignedPrincipalRoles = { principalRoles }
548+ onClose = { ( ) => setRemoveCatalogRoleModalVisible ( false ) }
549+ onSuccess = { handleRemoveCatalogRoleSuccess }
550+ />
471551 </ Space >
472552 )
473553}
0 commit comments