diff --git a/react/src/App.tsx b/react/src/App.tsx index 823d0b3775..b9005d32f7 100644 --- a/react/src/App.tsx +++ b/react/src/App.tsx @@ -57,8 +57,8 @@ const InteractiveLoginPage = React.lazy( ); const ImportAndRunPage = React.lazy(() => import('./pages/ImportAndRunPage')); -const ComputeSessionList = React.lazy( - () => import('./components/ComputeSessionList'), +const ComputeSessionListPage = React.lazy( + () => import('./pages/ComputeSessionListPage'), ); const AgentSummaryPage = React.lazy(() => import('./pages/AgentSummaryPage')); @@ -139,7 +139,7 @@ const router = createBrowserRouter([ handle: { labelKey: 'webui.menu.Sessions' }, element: ( - + ), }, diff --git a/react/src/components/BAILink.tsx b/react/src/components/BAILink.tsx index 6bfd558e82..21b663ba04 100644 --- a/react/src/components/BAILink.tsx +++ b/react/src/components/BAILink.tsx @@ -15,7 +15,7 @@ const useStyles = createStyles(({ css, token }) => ({ })); interface BAILinkProps extends LinkProps { - type: 'hover'; + type?: 'hover'; } const BAILink: React.FC = ({ type, ...linkProps }) => { const { styles } = useStyles(); diff --git a/react/src/components/ComputeSessionList.tsx b/react/src/components/ComputeSessionList.tsx deleted file mode 100644 index e67c4273df..0000000000 --- a/react/src/components/ComputeSessionList.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import BAIModal from './BAIModal'; -import ContainerLogModalWithLazyQueryLoader from './ComputeSessionNodeItems/ContainerLogModalWithLazyQueryLoader'; -import SessionDetailDrawer from './SessionDetailDrawer'; -import { Skeleton } from 'antd'; -import { Suspense, useEffect, useState } from 'react'; -import { StringParam, useQueryParam } from 'use-query-params'; - -const ComputeSessionList = () => { - const [sessionId, setSessionId] = useQueryParam('sessionDetail', StringParam); - - const [containerLogModalSessionId, setContainerLogModalSessionId] = - useState(); - useEffect(() => { - const handler = (e: any) => { - setContainerLogModalSessionId(e.detail); - }; - document.addEventListener('bai-open-session-log', handler); - return () => { - document.removeEventListener('bai-open-session-log', handler); - }; - }, []); - return ( - <> - { - setSessionId(null, 'replaceIn'); - }} - /> - {containerLogModalSessionId && ( - - - - } - > - { - setContainerLogModalSessionId(undefined); - }} - /> - - )} - - ); -}; - -export default ComputeSessionList; diff --git a/react/src/components/ComputeSessionNodeItems/SessionOccupiedSlot.tsx b/react/src/components/ComputeSessionNodeItems/SessionOccupiedSlot.tsx new file mode 100644 index 0000000000..c10d39883e --- /dev/null +++ b/react/src/components/ComputeSessionNodeItems/SessionOccupiedSlot.tsx @@ -0,0 +1,54 @@ +import { convertBinarySizeUnit } from '../../helper'; +import { useResourceSlotsDetails } from '../../hooks/backendai'; +import { SessionOccupiedSlotFragment$key } from './__generated__/SessionOccupiedSlotFragment.graphql'; +import { Divider, Typography } from 'antd'; +import graphql from 'babel-plugin-relay/macro'; +import _ from 'lodash'; +import React from 'react'; +import { useFragment } from 'react-relay'; + +interface OccupiedSlotViewProps { + sessionFrgmt: SessionOccupiedSlotFragment$key; + type: 'cpu' | 'mem' | 'accelerator'; +} +const SessionOccupiedSlot: React.FC = ({ + type, + sessionFrgmt, +}) => { + const { deviceMetadata } = useResourceSlotsDetails(); + const session = useFragment( + graphql` + fragment SessionOccupiedSlotFragment on ComputeSessionNode { + id + occupied_slots + } + `, + sessionFrgmt, + ); + + const occupiedSlots = JSON.parse(session.occupied_slots || '{}'); + + if (type === 'cpu') { + return occupiedSlots.cpu ?? '-'; + } else if (type === 'mem') { + const mem = occupiedSlots.mem ?? '-'; + return mem === '-' ? mem : convertBinarySizeUnit(mem, 'G')?.number + ' GiB'; + } else if (type === 'accelerator') { + const occupiedAccelerators = _.omit(occupiedSlots, ['cpu', 'mem']); + return _.isEmpty(occupiedAccelerators) + ? '-' + : _.map(occupiedAccelerators, (value, key) => { + return ( + <> + {value} + + + {deviceMetadata?.[key]?.human_readable_name} + + + ); + }); + } +}; + +export default SessionOccupiedSlot; diff --git a/react/src/components/ComputeSessionNodeItems/SessionReservation.tsx b/react/src/components/ComputeSessionNodeItems/SessionReservation.tsx index 9f0d9aed9f..c53f949a27 100644 --- a/react/src/components/ComputeSessionNodeItems/SessionReservation.tsx +++ b/react/src/components/ComputeSessionNodeItems/SessionReservation.tsx @@ -10,7 +10,8 @@ import { useFragment } from 'react-relay'; const SessionReservation: React.FC<{ sessionFrgmt: SessionReservationFragment$key; -}> = ({ sessionFrgmt }) => { + mode?: 'simple-elapsed' | 'detail'; +}> = ({ sessionFrgmt, mode = 'detail' }) => { const baiClient = useSuspendedBackendaiClient(); const { t } = useTranslation(); const session = useFragment( @@ -25,7 +26,7 @@ const SessionReservation: React.FC<{ ); return ( <> - {dayjs(session.created_at).format('lll')} + {mode !== 'simple-elapsed' && dayjs(session.created_at).format('lll')} { return session?.created_at @@ -36,14 +37,18 @@ const SessionReservation: React.FC<{ : '-'; }} delay={1000} - render={(intervalValue) => ( - - )} + render={(intervalValue) => + mode === 'simple-elapsed' ? ( + intervalValue + ) : ( + + ) + } /> ); diff --git a/react/src/components/ComputeSessionNodeItems/SessionStatusTag.tsx b/react/src/components/ComputeSessionNodeItems/SessionStatusTag.tsx index bc1c7291d2..4d8fb5ed68 100644 --- a/react/src/components/ComputeSessionNodeItems/SessionStatusTag.tsx +++ b/react/src/components/ComputeSessionNodeItems/SessionStatusTag.tsx @@ -12,6 +12,7 @@ import { useFragment } from 'react-relay'; interface SessionStatusTagProps { sessionFrgmt?: SessionStatusTagFragment$key | null; + showInfo?: boolean; } const statusTagColor = { //prepare @@ -49,6 +50,7 @@ const statusInfoTagColor = { }; const SessionStatusTag: React.FC = ({ sessionFrgmt, + showInfo, }) => { const session = useFragment( graphql` @@ -64,7 +66,7 @@ const SessionStatusTag: React.FC = ({ const { token } = theme.useToken(); return session ? ( - _.isEmpty(session.status_info) ? ( + _.isEmpty(session.status_info) || !showInfo ? ( = ({ `, sessionFrgmt, ); + const [isForce, setIsForce] = useState(false); const userRole = useCurrentUserRole(); diff --git a/react/src/components/ComputeSessionNodeList.tsx b/react/src/components/ComputeSessionNodeList.tsx new file mode 100644 index 0000000000..9ff22837e2 --- /dev/null +++ b/react/src/components/ComputeSessionNodeList.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +const ComputeSessionNodeList = () => { + return
ComputeSessionNodeList
; +}; + +export default ComputeSessionNodeList; diff --git a/react/src/components/SessionDetailContent.tsx b/react/src/components/SessionDetailContent.tsx index fb7d4cfd67..b228dceb0d 100644 --- a/react/src/components/SessionDetailContent.tsx +++ b/react/src/components/SessionDetailContent.tsx @@ -166,7 +166,7 @@ const SessionDetailContent: React.FC<{ label={t('session.Status')} contentStyle={{ display: 'flex', gap: token.marginSM }} > - + {/*