diff --git a/react/src/App.tsx b/react/src/App.tsx index 3e2da8daf..76f96dd88 100644 --- a/react/src/App.tsx +++ b/react/src/App.tsx @@ -7,7 +7,7 @@ import { import Flex from './components/Flex'; import LocationStateBreadCrumb from './components/LocationStateBreadCrumb'; import MainLayout from './components/MainLayout/MainLayout'; -import { useSuspendedBackendaiClient } from './hooks'; +import WebUINavigate from './components/WebUINavigate'; import { useBAISettingUserState } from './hooks/useBAISetting'; import Page401 from './pages/Page401'; import Page404 from './pages/Page404'; @@ -16,7 +16,7 @@ import { Skeleton, theme } from 'antd'; import React, { Suspense } from 'react'; import { FC } from 'react'; import { - Navigate, + IndexRouteObject, RouterProvider, createBrowserRouter, } from 'react-router-dom'; @@ -35,7 +35,6 @@ const StorageHostSettingPage = React.lazy( () => import('./pages/StorageHostSettingPage'), ); const UserSettingsPage = React.lazy(() => import('./pages/UserSettingsPage')); -const SessionListPage = React.lazy(() => import('./pages/SessionListPage')); const SessionLauncherPage = React.lazy( () => import('./pages/SessionLauncherPage'), ); @@ -61,19 +60,13 @@ const ComputeSessionList = React.lazy( () => import('./components/ComputeSessionList'), ); -const RedirectToSummary = () => { - useSuspendedBackendaiClient(); - const pathName = '/summary'; - document.dispatchEvent( - new CustomEvent('move-to-from-react', { - detail: { - path: pathName, - // params: options?.params, - }, - }), - ); - return ; -}; +interface CustomHandle { + title?: string; + labelKey?: string; +} +export interface WebUIRouteObject extends IndexRouteObject { + handle: CustomHandle; +} const router = createBrowserRouter([ { @@ -105,21 +98,20 @@ const router = createBrowserRouter([ ), - handle: { labelKey: 'webui.menu.Summary' }, children: [ { path: '/', - element: , + element: , }, { //for electron dev mode path: '/build/electron-app/app/index.html', - element: , + element: , }, { //for electron prod mode path: '/app/index.html', - element: , + element: , }, { path: '/summary', @@ -150,22 +142,65 @@ const router = createBrowserRouter([ ), }, { - path: '/serving', - element: ( - - - - ), - handle: { labelKey: 'webui.menu.Serving' }, + path: '/session', + handle: { labelKey: 'webui.menu.Sessions' }, + children: [ + { + path: '', + element: , + }, + { + path: '/session/start', + // handle: { labelKey: 'session.launcher.StartNewSession' }, + Component: () => { + const { token } = theme.useToken(); + return ( + + + + + + } + > + + + + ); + }, + handle: { labelKey: 'session.launcher.StartNewSession' }, + }, + ], }, { - path: '/serving/:serviceId', - element: ( - - - - ), - handle: { labelKey: 'modelService.RoutingInfo' }, + path: '/serving', + + handle: { labelKey: 'webui.menu.Serving' }, + children: [ + { + path: '', + element: ( + + + + ), + }, + { + path: '/serving/:serviceId', + element: ( + + + + ), + handle: { labelKey: 'modelService.RoutingInfo' }, + }, + ], }, { path: '/service', @@ -173,7 +208,7 @@ const router = createBrowserRouter([ children: [ { path: '', - element: , + element: , }, { path: 'start', @@ -305,37 +340,6 @@ const router = createBrowserRouter([ handle: { labelKey: 'webui.UNAUTHORIZEDACCESS' }, Component: Page401, }, - { - path: '/session', - handle: { labelKey: 'webui.menu.Sessions' }, - Component: SessionListPage, - }, - { - path: '/session/start', - // handle: { labelKey: 'session.launcher.StartNewSession' }, - Component: () => { - const { token } = theme.useToken(); - return ( - - - - - - } - > - - - - ); - }, - }, // Leave empty tag for plugin pages. { path: '*', diff --git a/react/src/components/MainLayout/WebUISider.tsx b/react/src/components/MainLayout/WebUISider.tsx index ae2351eea..94b5e3479 100644 --- a/react/src/components/MainLayout/WebUISider.tsx +++ b/react/src/components/MainLayout/WebUISider.tsx @@ -7,6 +7,7 @@ import BAIMenu from '../BAIMenu'; import BAISider, { BAISiderProps } from '../BAISider'; import Flex from '../Flex'; import SignoutModal from '../SignoutModal'; +import WebUILink from '../WebUILink'; import { PluginPage, WebUIPluginType } from './MainLayout'; import { ApiOutlined, @@ -71,42 +72,52 @@ const WebUISider: React.FC = (props) => { const generalMenu = filterEmptyItem([ { - label: t('webui.menu.Summary'), + label: {t('webui.menu.Summary')}, icon: , key: 'summary', }, { - label: t('webui.menu.Sessions'), + label: {t('webui.menu.Sessions')}, icon: , key: 'job', }, supportServing && { - label: t('webui.menu.Serving'), + label: {t('webui.menu.Serving')}, icon: , key: 'serving', }, { - label: t('webui.menu.Import&Run'), + label: {t('webui.menu.Import&Run')}, icon: , key: 'import', }, { - label: t('webui.menu.Data&Storage'), + label: {t('webui.menu.Data&Storage')}, icon: , key: 'data', }, supportUserCommittedImage && { - label: t('webui.menu.MyEnvironments'), + label: ( + + {t('webui.menu.MyEnvironments')} + + ), icon: , key: 'my-environment', }, !isHideAgents && { - label: t('webui.menu.AgentSummary'), + label: ( + + {t('webui.menu.AgentSummary')} + + ), icon: , key: 'agent-summary', }, { - label: t('webui.menu.Statistics'), + label: ( + {t('webui.menu.Statistics')} + ), icon: , key: 'statistics', }, @@ -122,17 +133,23 @@ const WebUISider: React.FC = (props) => { const adminMenu: MenuProps['items'] = [ { - label: t('webui.menu.Users'), + label: {t('webui.menu.Users')}, icon: , key: 'credential', }, { - label: t('webui.menu.Environments'), + label: ( + {t('webui.menu.Environments')} + ), icon: , key: 'environment', }, { - label: t('webui.menu.ResourcePolicy'), + label: ( + + {t('webui.menu.ResourcePolicy')} + + ), icon: , key: 'resource-policy', }, @@ -140,22 +157,28 @@ const WebUISider: React.FC = (props) => { const superAdminMenu: MenuProps['items'] = [ { - label: t('webui.menu.Resources'), + label: {t('webui.menu.Resources')}, icon: , key: 'agent', }, { - label: t('webui.menu.Configurations'), + label: ( + {t('webui.menu.Configurations')} + ), icon: , key: 'settings', }, { - label: t('webui.menu.Maintenance'), + label: ( + {t('webui.menu.Maintenance')} + ), icon: , key: 'maintenance', }, { - label: t('webui.menu.Information'), + label: ( + {t('webui.menu.Information')} + ), icon: , key: 'information', }, diff --git a/react/src/components/WebUILink.tsx b/react/src/components/WebUILink.tsx new file mode 100644 index 000000000..5ac42d369 --- /dev/null +++ b/react/src/components/WebUILink.tsx @@ -0,0 +1,33 @@ +import _ from 'lodash'; +import React from 'react'; +import { Link, LinkProps } from 'react-router-dom'; + +interface WebUILinkProps extends LinkProps { + options?: { + params?: any; + }; +} + +const WebUILink: React.FC = ({ options, ...props }) => { + return ( + { + props.onClick?.(e); + const pathName = _.isString(props.to) + ? props.to + : props.to.pathname || ''; + document.dispatchEvent( + new CustomEvent('move-to-from-react', { + detail: { + path: pathName, + params: options?.params, + }, + }), + ); + }} + /> + ); +}; + +export default WebUILink; diff --git a/react/src/components/WebUINavigate.tsx b/react/src/components/WebUINavigate.tsx new file mode 100644 index 000000000..fa16fa052 --- /dev/null +++ b/react/src/components/WebUINavigate.tsx @@ -0,0 +1,29 @@ +import { useSuspendedBackendaiClient } from '../hooks'; +import _ from 'lodash'; +import React, { useEffect } from 'react'; +import { Navigate, NavigateProps } from 'react-router-dom'; + +interface WebUINavigateProps extends NavigateProps { + options?: { + params?: any; + }; +} +const WebUINavigate: React.FC = ({ options, ...props }) => { + useSuspendedBackendaiClient(); + const pathName = _.isString(props.to) ? props.to : props.to.pathname || ''; + useEffect(() => { + document.dispatchEvent( + new CustomEvent('move-to-from-react', { + detail: { + path: pathName, + params: options?.params, + }, + }), + ); + // Don't need to consider options.params + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [pathName]); + return ; +}; + +export default WebUINavigate;