mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: command bar admin menu improvements (#9689)
This commit is contained in:
		
							parent
							
								
									6432262be5
								
							
						
					
					
						commit
						b9a7c0cda6
					
				| @ -1,16 +1,19 @@ | ||||
| import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; | ||||
| import { adminRoutes } from './oldAdminRoutes'; | ||||
| import { adminRoutes as oldAdminRoutes } from './oldAdminRoutes'; | ||||
| import { adminRoutes } from './adminRoutes'; | ||||
| import { useInstanceStatus } from 'hooks/api/getters/useInstanceStatus/useInstanceStatus'; | ||||
| import { filterAdminRoutes } from './filterAdminRoutes'; | ||||
| import { filterByConfig, mapRouteLink } from 'component/common/util'; | ||||
| import { useUiFlag } from 'hooks/useUiFlag'; | ||||
| 
 | ||||
| export const useAdminRoutes = () => { | ||||
|     const newAdminUIEnabled = useUiFlag('adminNavUI'); | ||||
|     const { uiConfig, isPro, isEnterprise } = useUiConfig(); | ||||
|     const { isBilling } = useInstanceStatus(); | ||||
|     const routes = [...adminRoutes]; | ||||
|     const routes = newAdminUIEnabled ? [...adminRoutes] : [...oldAdminRoutes]; | ||||
| 
 | ||||
|     if (uiConfig.flags.UNLEASH_CLOUD) { | ||||
|         const adminBillingMenuItem = adminRoutes.findIndex( | ||||
|         const adminBillingMenuItem = routes.findIndex( | ||||
|             (route) => route.title === 'Billing & invoices', | ||||
|         ); | ||||
|         routes[adminBillingMenuItem] = { | ||||
|  | ||||
							
								
								
									
										22
									
								
								frontend/src/component/commandBar/ButtonItemIcon.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								frontend/src/component/commandBar/ButtonItemIcon.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| import { IconRenderer } from 'component/layout/MainLayout/NavigationSidebar/IconRenderer'; | ||||
| import InsightsIcon from '@mui/icons-material/Insights'; | ||||
| import PlaygroundIcon from '@mui/icons-material/AutoFixNormal'; | ||||
| import { ProjectIcon } from 'component/common/ProjectIcon/ProjectIcon'; | ||||
| 
 | ||||
| export const ButtonItemIcon = ({ | ||||
|     path, | ||||
| }: { | ||||
|     path: string; | ||||
| }) => { | ||||
|     if (path === '/projects') { | ||||
|         return <ProjectIcon />; | ||||
|     } | ||||
|     if (path === '/playground') { | ||||
|         return <PlaygroundIcon />; | ||||
|     } | ||||
|     if (path === '/insights') { | ||||
|         return <InsightsIcon />; | ||||
|     } | ||||
| 
 | ||||
|     return <IconRenderer path={path} />; | ||||
| }; | ||||
| @ -18,7 +18,6 @@ import { | ||||
|     type CommandResultGroupItem, | ||||
| } from './RecentlyVisited/CommandResultGroup'; | ||||
| import { CommandPageSuggestions } from './CommandPageSuggestions'; | ||||
| import { useRoutes } from 'component/layout/MainLayout/NavigationSidebar/useRoutes'; | ||||
| import { useAsyncDebounce } from 'react-table'; | ||||
| import useProjects from 'hooks/api/getters/useProjects/useProjects'; | ||||
| import { | ||||
| @ -31,6 +30,7 @@ import { CommandSearchPages } from './CommandSearchPages'; | ||||
| import { CommandBarFeedback } from './CommandBarFeedback'; | ||||
| import { RecentlyVisitedRecorder } from './RecentlyVisitedRecorder'; | ||||
| import { ScreenReaderOnly } from 'component/common/ScreenReaderOnly/ScreenReaderOnly'; | ||||
| import { useCommandBarRoutes } from './useCommandBarRoutes'; | ||||
| 
 | ||||
| export const CommandResultsPaper = styled(Paper)(({ theme }) => ({ | ||||
|     position: 'absolute', | ||||
| @ -101,12 +101,6 @@ const StyledClose = styled(Close)(({ theme }) => ({ | ||||
|     fontSize: theme.typography.body1.fontSize, | ||||
| })); | ||||
| 
 | ||||
| interface IPageRouteInfo { | ||||
|     path: string; | ||||
|     route: string; | ||||
|     title: string; | ||||
| } | ||||
| 
 | ||||
| export const CommandBar = () => { | ||||
|     const { trackEvent } = usePlausibleTracker(); | ||||
|     const searchInputRef = useRef<HTMLInputElement>(null); | ||||
| @ -124,19 +118,7 @@ export const CommandBar = () => { | ||||
|         useState<CommandQueryCounter>({ query: '', count: 0 }); | ||||
|     const [hasNoResults, setHasNoResults] = useState(false); | ||||
|     const [value, setValue] = useState<string>(''); | ||||
|     const { routes } = useRoutes(); | ||||
|     const allRoutes: Record<string, IPageRouteInfo> = {}; | ||||
|     for (const route of [ | ||||
|         ...routes.mainNavRoutes, | ||||
|         ...routes.adminRoutes, | ||||
|         ...routes.primaryRoutes, | ||||
|     ]) { | ||||
|         allRoutes[route.path] = { | ||||
|             path: route.path, | ||||
|             route: route.route, | ||||
|             title: route.title, | ||||
|         }; | ||||
|     } | ||||
|     const { allRoutes } = useCommandBarRoutes(); | ||||
| 
 | ||||
|     const hideSuggestions = () => { | ||||
|         setShowSuggestions(false); | ||||
| @ -159,7 +141,7 @@ export const CommandBar = () => { | ||||
|         setSearchedProjects(mappedProjects); | ||||
| 
 | ||||
|         const filteredPages = Object.values(allRoutes).filter((route) => | ||||
|             route.title.toLowerCase().includes(query.toLowerCase()), | ||||
|             route.searchText.toLowerCase().includes(query.toLowerCase()), | ||||
|         ); | ||||
|         const mappedPages = filteredPages.map((page) => ({ | ||||
|             name: page.title, | ||||
|  | ||||
| @ -9,7 +9,7 @@ import { | ||||
|     type CommandResultGroupItem, | ||||
| } from './RecentlyVisited/CommandResultGroup'; | ||||
| import { ListItemButton } from '@mui/material'; | ||||
| import { IconRenderer } from 'component/layout/MainLayout/NavigationSidebar/IconRenderer'; | ||||
| import { ButtonItemIcon } from './ButtonItemIcon'; | ||||
| 
 | ||||
| export const CommandSearchPages = ({ | ||||
|     items, | ||||
| @ -50,7 +50,7 @@ export const CommandSearchPages = ({ | ||||
|                     sx={listItemButtonStyle} | ||||
|                 > | ||||
|                     <StyledListItemIcon> | ||||
|                         <IconRenderer path={item.link} /> | ||||
|                         <ButtonItemIcon path={item.link} /> | ||||
|                     </StyledListItemIcon> | ||||
|                     <StyledListItemText> | ||||
|                         <StyledButtonTypography color='textPrimary'> | ||||
|  | ||||
| @ -10,14 +10,12 @@ import { | ||||
| import { Link } from 'react-router-dom'; | ||||
| import type { Theme } from '@mui/material/styles/createTheme'; | ||||
| import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; | ||||
| import { IconRenderer } from 'component/layout/MainLayout/NavigationSidebar/IconRenderer'; | ||||
| import InsightsIcon from '@mui/icons-material/Insights'; | ||||
| import PlaygroundIcon from '@mui/icons-material/AutoFixNormal'; | ||||
| import { TooltipResolver } from 'component/common/TooltipResolver/TooltipResolver'; | ||||
| import { usePlausibleTracker } from 'hooks/usePlausibleTracker'; | ||||
| import useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectOverview'; | ||||
| import { Children } from 'react'; | ||||
| import { ProjectIcon } from 'component/common/ProjectIcon/ProjectIcon'; | ||||
| import { ButtonItemIcon } from '../ButtonItemIcon'; | ||||
| 
 | ||||
| export const listItemButtonStyle = (theme: Theme) => ({ | ||||
|     border: `1px solid transparent`, | ||||
| @ -48,24 +46,6 @@ export interface CommandResultGroupItem { | ||||
|     description?: string | null; | ||||
| } | ||||
| 
 | ||||
| const ButtonItemIcon = ({ | ||||
|     path, | ||||
| }: { | ||||
|     path: string; | ||||
| }) => { | ||||
|     if (path === '/projects') { | ||||
|         return <ProjectIcon />; | ||||
|     } | ||||
|     if (path === '/playground') { | ||||
|         return <PlaygroundIcon />; | ||||
|     } | ||||
|     if (path === '/insights') { | ||||
|         return <InsightsIcon />; | ||||
|     } | ||||
| 
 | ||||
|     return <IconRenderer path={path} />; | ||||
| }; | ||||
| 
 | ||||
| export const RecentlyVisitedPathButton = ({ | ||||
|     keyName, | ||||
|     path, | ||||
|  | ||||
							
								
								
									
										55
									
								
								frontend/src/component/commandBar/useCommandBarRoutes.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								frontend/src/component/commandBar/useCommandBarRoutes.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,55 @@ | ||||
| import { adminGroups } from 'component/admin/adminRoutes'; | ||||
| import { useRoutes } from 'component/layout/MainLayout/NavigationSidebar/useRoutes'; | ||||
| import { useUiFlag } from 'hooks/useUiFlag'; | ||||
| import type { INavigationMenuItem } from 'interfaces/route'; | ||||
| import { useMemo } from 'react'; | ||||
| 
 | ||||
| interface IPageRouteInfo { | ||||
|     path: string; | ||||
|     route: string; | ||||
|     title: string; | ||||
|     searchText: string; | ||||
| } | ||||
| 
 | ||||
| export const useCommandBarRoutes = () => { | ||||
|     const newAdminUIEnabled = useUiFlag('adminNavUI'); | ||||
|     const { routes } = useRoutes(); | ||||
|     const getSearchText = (route: INavigationMenuItem, title: string) => { | ||||
|         if (route.group && adminGroups[route.group]) { | ||||
|             return `${title} ${route.path} ${route.group} ${adminGroups[route.group]}`; | ||||
|         } | ||||
| 
 | ||||
|         return `${title} ${route.path}`; | ||||
|     }; | ||||
| 
 | ||||
|     const getRouteTitle = (route: INavigationMenuItem) => { | ||||
|         if (route.path === '/admin') { | ||||
|             return 'Admin settings'; | ||||
|         } | ||||
| 
 | ||||
|         return route.title; | ||||
|     }; | ||||
|     return useMemo(() => { | ||||
|         const allRoutes: Record<string, IPageRouteInfo> = {}; | ||||
|         for (const route of [ | ||||
|             ...routes.mainNavRoutes, | ||||
|             ...routes.adminRoutes, | ||||
|             ...routes.primaryRoutes, | ||||
|         ]) { | ||||
|             const title = getRouteTitle(route); | ||||
|             allRoutes[route.path] = { | ||||
|                 path: route.path, | ||||
|                 route: route.route, | ||||
|                 title: title, | ||||
|                 searchText: newAdminUIEnabled | ||||
|                     ? getSearchText(route, title) | ||||
|                     : title, | ||||
|             }; | ||||
|         } | ||||
| 
 | ||||
|         return { | ||||
|             allRoutes, | ||||
|             newAdminUIEnabled, | ||||
|         }; | ||||
|     }, [routes]); | ||||
| }; | ||||
| @ -13,7 +13,9 @@ import UsersIcon from '@mui/icons-material/GroupOutlined'; | ||||
| import ServiceAccountIcon from '@mui/icons-material/Computer'; | ||||
| import GroupsIcon from '@mui/icons-material/GroupsOutlined'; | ||||
| import RoleIcon from '@mui/icons-material/AdminPanelSettingsOutlined'; | ||||
| import SettingsIcon from '@mui/icons-material/Settings'; | ||||
| import SearchIcon from '@mui/icons-material/Search'; | ||||
| import InsightsIcon from '@mui/icons-material/Insights'; | ||||
| import ApiAccessIcon from '@mui/icons-material/KeyOutlined'; | ||||
| import SingleSignOnIcon from '@mui/icons-material/AssignmentOutlined'; | ||||
| import NetworkIcon from '@mui/icons-material/HubOutlined'; | ||||
| @ -39,6 +41,7 @@ const icons: Record< | ||||
|     typeof SvgIcon | FC<ComponentProps<typeof SvgIcon>> | ||||
| > = { | ||||
|     '/search': SearchIcon, | ||||
|     '/insights': InsightsIcon, | ||||
|     '/applications': ApplicationsIcon, | ||||
|     '/context': ContextFieldsIcon, | ||||
|     '/feature-toggle-type': FlagTypesIcon, | ||||
| @ -47,13 +50,24 @@ const icons: Record< | ||||
|     '/strategies': CustomStrategiesIcon, | ||||
|     '/tag-types': TagTypesIcon, | ||||
|     '/environments': EnvironmentsIcon, | ||||
|     '/admin': SettingsIcon, | ||||
|     '/admin/users': UsersIcon, | ||||
|     '/admin/service-accounts': ServiceAccountIcon, | ||||
|     '/admin/groups': GroupsIcon, | ||||
|     '/admin/roles': RoleIcon, | ||||
|     '/admin/roles/project-roles': RoleIcon, | ||||
|     '/admin/api': ApiAccessIcon, | ||||
|     '/admin/auth': SingleSignOnIcon, | ||||
|     '/admin/auth/saml': SingleSignOnIcon, | ||||
|     '/admin/auth/scim': SingleSignOnIcon, | ||||
|     '/admin/auth/password': SingleSignOnIcon, | ||||
|     '/admin/auth/google': SingleSignOnIcon, | ||||
|     '/admin/network': NetworkIcon, | ||||
|     '/admin/network/traffic': NetworkIcon, | ||||
|     '/admin/network/data-usage': NetworkIcon, | ||||
|     '/admin/network/frontend-data-usage': NetworkIcon, | ||||
|     '/admin/network/connected-edges': NetworkIcon, | ||||
|     '/admin/network/backend-connections': NetworkIcon, | ||||
|     '/admin/maintenance': MaintenanceIcon, | ||||
|     '/admin/banners': BannersIcon, | ||||
|     '/admin/instance': InstanceStatsIcon, | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user