44} from '@linode/queries' ;
55import { Select , Typography , useTheme } from '@linode/ui' ;
66import Grid from '@mui/material/Grid' ;
7- import { useSearch } from '@tanstack/react-router' ;
7+ import { useNavigate , useSearch } from '@tanstack/react-router' ;
88import React from 'react' ;
99
1010import { ActionMenu } from 'src/components/ActionMenu/ActionMenu' ;
@@ -55,38 +55,62 @@ interface Props {
5555 username ?: string ;
5656}
5757
58+ const DEFAULTS_ENTITIES_URL = '/iam/roles/defaults/entity-access' ;
59+ const USER_ENTITIES_URL = '/iam/users/$username/entities' ;
60+
5861export const AssignedEntitiesTable = ( { username } : Props ) => {
5962 const theme = useTheme ( ) ;
6063 const { data : permissions } = usePermissions ( 'account' , [
6164 'is_account_admin' ,
6265 'update_default_delegate_access' ,
6366 'list_entities' ,
6467 ] ) ;
68+ const navigate = useNavigate ( ) ;
6569
6670 const { isDefaultDelegationRolesForChildAccount } =
6771 useIsDefaultDelegationRolesForChildAccount ( ) ;
6872
69- const { selectedRole : selectedRoleSearchParam } = useSearch ( {
70- strict : false ,
73+ const {
74+ query : queryParam ,
75+ entityType : entityTypeParam ,
76+ order : orderParam ,
77+ selectedRole : selectedRoleSearchParam ,
78+ orderBy : orderByParam ,
79+ } = useSearch ( {
80+ from : isDefaultDelegationRolesForChildAccount
81+ ? DEFAULTS_ENTITIES_URL
82+ : USER_ENTITIES_URL ,
7183 } ) ;
7284
73- const [ order , setOrder ] = React . useState < 'asc' | 'desc' > ( 'asc' ) ;
74- const [ orderBy , setOrderBy ] = React . useState < OrderByKeys > ( 'entity_name' ) ;
85+ const order : 'asc' | 'desc' = orderParam ?? 'asc' ;
86+
87+ const ORDERABLE_KEYS = [ 'entity_name' , 'entity_type' , 'role_name' ] as const ;
88+ const isValidOrderBy = ( v : unknown ) : v is OrderByKeys =>
89+ ORDERABLE_KEYS . includes ( v as OrderByKeys ) ;
90+ const orderBy : OrderByKeys = isValidOrderBy ( orderByParam )
91+ ? orderByParam
92+ : 'entity_name' ;
7593
7694 const handleOrderChange = ( newOrderBy : OrderByKeys ) => {
77- if ( orderBy === newOrderBy ) {
78- setOrder ( order === 'asc' ? 'desc' : 'asc' ) ;
79- } else {
80- setOrderBy ( newOrderBy ) ;
81- setOrder ( 'asc' ) ;
82- }
95+ const nextOrder : 'asc' | 'desc' =
96+ orderBy === newOrderBy ? ( order === 'asc' ? 'desc' : 'asc' ) : 'asc' ;
97+ navigate ( {
98+ to : isDefaultDelegationRolesForChildAccount
99+ ? DEFAULTS_ENTITIES_URL
100+ : USER_ENTITIES_URL ,
101+ params : isDefaultDelegationRolesForChildAccount
102+ ? undefined
103+ : { username : username || '' } ,
104+ search : ( prev ) => ( {
105+ ...prev ,
106+ order : nextOrder ,
107+ orderBy : newOrderBy ,
108+ } ) ,
109+ } ) ;
83110 } ;
84111
85- const [ query , setQuery ] = React . useState ( selectedRoleSearchParam ?? '' ) ;
86-
87- const [ entityType , setEntityType ] = React . useState < null | SelectOption > (
88- ALL_ENTITIES_OPTION
89- ) ;
112+ // Use the router `query` param, falling back to `selectedRole` for initial value
113+ const appliedQuery = queryParam ?? selectedRoleSearchParam ?? '' ;
90114
91115 const [ drawerMode , setDrawerMode ] =
92116 React . useState < DrawerModes > ( 'assign-role' ) ;
@@ -149,6 +173,14 @@ export const AssignedEntitiesTable = ({ username }: Props) => {
149173 return { filterableOptions, roles } ;
150174 } , [ assignedRoles , entities ] ) ;
151175
176+ const selectedEntityTypeOption = React . useMemo < null | SelectOption > ( ( ) => {
177+ const value = entityTypeParam ?? ALL_ENTITIES_OPTION . value ;
178+ return (
179+ filterableOptions . find ( ( opt ) => opt . value === value ) ||
180+ ALL_ENTITIES_OPTION
181+ ) ;
182+ } , [ filterableOptions , entityTypeParam ] ) ;
183+
152184 const handleChangeRole = ( role : EntitiesRole , mode : DrawerModes ) => {
153185 setIsChangeRoleForEntityDrawerOpen ( true ) ;
154186 setSelectedRole ( role ) ;
@@ -176,9 +208,9 @@ export const AssignedEntitiesTable = ({ username }: Props) => {
176208 } ;
177209
178210 const filteredRoles = getFilteredRoles ( {
179- entityType : entityType ?. value as 'all' | EntityType ,
211+ entityType : entityTypeParam ?? 'all' ,
180212 getSearchableFields,
181- query,
213+ query : appliedQuery ,
182214 roles,
183215 } ) as EntitiesRole [ ] ;
184216
@@ -197,8 +229,8 @@ export const AssignedEntitiesTable = ({ username }: Props) => {
197229
198230 const pagination = usePaginationV2 ( {
199231 currentRoute : isDefaultDelegationRolesForChildAccount
200- ? '/iam/roles/defaults/entity-access'
201- : `/iam/users/$username/entities` ,
232+ ? DEFAULTS_ENTITIES_URL
233+ : USER_ENTITIES_URL ,
202234 initialPage : 1 ,
203235 preferenceKey : ENTITIES_TABLE_PREFERENCE_KEY ,
204236 clientSidePaginationData : filteredAndSortedRoles ,
@@ -309,24 +341,50 @@ export const AssignedEntitiesTable = ({ username }: Props) => {
309341 hideLabel
310342 label = "Filter"
311343 onSearch = { ( value ) => {
312- pagination . handlePageChange ( 1 ) ;
313- setQuery ( value ) ;
344+ navigate ( {
345+ to : isDefaultDelegationRolesForChildAccount
346+ ? DEFAULTS_ENTITIES_URL
347+ : USER_ENTITIES_URL ,
348+ params :
349+ isDefaultDelegationRolesForChildAccount && ! username
350+ ? undefined
351+ : username ,
352+ search : ( prev ) => ( {
353+ ...prev ,
354+ page : 1 ,
355+ query : value !== '' ? value : undefined ,
356+ } ) ,
357+ } ) ;
314358 } }
315359 placeholder = "Search"
316360 sx = { { height : 34 } }
317- value = { query }
361+ value = { appliedQuery }
318362 />
319363 < Select
320364 hideLabel
321365 label = "Select type"
322366 onChange = { ( _ , selected ) => {
323- pagination . handlePageChange ( 1 ) ;
324- setEntityType ( selected ?? null ) ;
367+ const nextEntityType = ( selected ?. value ??
368+ ALL_ENTITIES_OPTION . value ) as 'all' | EntityType ;
369+ navigate ( {
370+ to : isDefaultDelegationRolesForChildAccount
371+ ? DEFAULTS_ENTITIES_URL
372+ : USER_ENTITIES_URL ,
373+ params :
374+ isDefaultDelegationRolesForChildAccount && ! username
375+ ? undefined
376+ : username ,
377+ search : ( prev ) => ( {
378+ ...prev ,
379+ page : 1 ,
380+ entityType : nextEntityType ,
381+ } ) ,
382+ } ) ;
325383 } }
326384 options = { filterableOptions }
327385 placeholder = "All Entities"
328386 sx = { { minWidth : 250 } }
329- value = { entityType }
387+ value = { selectedEntityTypeOption }
330388 />
331389 </ Grid >
332390 < Table aria-label = "Assigned Entities" >
0 commit comments