Skip to content

Commit

Permalink
feat: Session list NEO
Browse files Browse the repository at this point in the history
  • Loading branch information
yomybaby committed Dec 11, 2024
1 parent 8252a10 commit d3fe67a
Show file tree
Hide file tree
Showing 13 changed files with 428 additions and 83 deletions.
6 changes: 3 additions & 3 deletions react/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'));

Expand Down Expand Up @@ -139,7 +139,7 @@ const router = createBrowserRouter([
handle: { labelKey: 'webui.menu.Sessions' },
element: (
<BAIErrorBoundary>
<ComputeSessionList />
<ComputeSessionListPage />
</BAIErrorBoundary>
),
},
Expand Down
2 changes: 1 addition & 1 deletion react/src/components/BAILink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const useStyles = createStyles(({ css, token }) => ({
}));

interface BAILinkProps extends LinkProps {
type: 'hover';
type?: 'hover';
}
const BAILink: React.FC<BAILinkProps> = ({ type, ...linkProps }) => {
const { styles } = useStyles();
Expand Down
65 changes: 0 additions & 65 deletions react/src/components/ComputeSessionList.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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<OccupiedSlotViewProps> = ({
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 (
<>
<Typography.Text>{value}</Typography.Text>
<Divider type="vertical" />
<Typography.Text>
{deviceMetadata?.[key]?.human_readable_name}
</Typography.Text>
</>
);
});
}
};

export default SessionOccupiedSlot;
25 changes: 15 additions & 10 deletions react/src/components/ComputeSessionNodeItems/SessionReservation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -25,7 +26,7 @@ const SessionReservation: React.FC<{
);
return (
<>
{dayjs(session.created_at).format('lll')}
{mode !== 'simple-elapsed' && dayjs(session.created_at).format('lll')}
<BAIIntervalView
callback={() => {
return session?.created_at
Expand All @@ -36,14 +37,18 @@ const SessionReservation: React.FC<{
: '-';
}}
delay={1000}
render={(intervalValue) => (
<DoubleTag
values={[
{ label: t('session.ElapsedTime') },
{ label: intervalValue },
]}
/>
)}
render={(intervalValue) =>
mode === 'simple-elapsed' ? (
intervalValue
) : (
<DoubleTag
values={[
{ label: t('session.ElapsedTime') },
{ label: intervalValue },
]}
/>
)
}
/>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useFragment } from 'react-relay';

interface SessionStatusTagProps {
sessionFrgmt?: SessionStatusTagFragment$key | null;
showInfo?: boolean;
}
const statusTagColor = {
//prepare
Expand Down Expand Up @@ -49,6 +50,7 @@ const statusInfoTagColor = {
};
const SessionStatusTag: React.FC<SessionStatusTagProps> = ({
sessionFrgmt,
showInfo,
}) => {
const session = useFragment(
graphql`
Expand All @@ -64,7 +66,7 @@ const SessionStatusTag: React.FC<SessionStatusTagProps> = ({
const { token } = theme.useToken();

return session ? (
_.isEmpty(session.status_info) ? (
_.isEmpty(session.status_info) || !showInfo ? (
<Tag
color={
session.status ? _.get(statusTagColor, session.status) : undefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ const TerminateSessionModal: React.FC<TerminateSessionModalProps> = ({
`,
sessionFrgmt,
);

const [isForce, setIsForce] = useState(false);
const userRole = useCurrentUserRole();

Expand Down
7 changes: 7 additions & 0 deletions react/src/components/ComputeSessionNodeList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react';

const ComputeSessionNodeList = () => {
return <div>ComputeSessionNodeList</div>;
};

export default ComputeSessionNodeList;
2 changes: 1 addition & 1 deletion react/src/components/SessionDetailContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ const SessionDetailContent: React.FC<{
label={t('session.Status')}
contentStyle={{ display: 'flex', gap: token.marginSM }}
>
<SessionStatusTag sessionFrgmt={session} />
<SessionStatusTag sessionFrgmt={session} showInfo />
{/* <Button type="text" icon={<TriangleAlertIcon />} /> */}
</Descriptions.Item>
<Descriptions.Item label={t('session.SessionType')}>
Expand Down
132 changes: 132 additions & 0 deletions react/src/components/SessionNodes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import BAILink from './BAILink';
import BAITable from './BAITable';
import SessionOccupiedSlot from './ComputeSessionNodeItems/SessionOccupiedSlot';
import SessionReservation from './ComputeSessionNodeItems/SessionReservation';
import SessionStatusTag from './ComputeSessionNodeItems/SessionStatusTag';
import SessionDetailDrawer from './SessionDetailDrawer';
import { SessionNodesFragment$key } from './__generated__/SessionNodesFragment.graphql';
import { TableProps } from 'antd/lib';
import graphql from 'babel-plugin-relay/macro';
import _ from 'lodash';

Check warning on line 10 in react/src/components/SessionNodes.tsx

View workflow job for this annotation

GitHub Actions / coverage

'_' is defined but never used
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useFragment } from 'react-relay';

interface SessionNodesProps extends Omit<TableProps, 'dataSource' | 'columns'> {
sessionsFrgmt: SessionNodesFragment$key;
}
const SessionNodes: React.FC<SessionNodesProps> = ({
sessionsFrgmt,
...tableProps
}) => {
const { t } = useTranslation();
const [selectedSessionId, setSelectedSessionId] = useState<string>();

const sessions = useFragment(
graphql`
fragment SessionNodesFragment on ComputeSessionNode @relay(plural: true) {
id
row_id
name
...SessionStatusTagFragment
...SessionReservationFragment
...SessionOccupiedSlotFragment
}
`,
sessionsFrgmt,
);

return (
<>
<BAITable
dataSource={sessions}
columns={[
{
key: 'name',
title: t('session.SessionName'),
dataIndex: 'name',
render: (name: string, session) => {
return (
<BAILink
to={'#'}
type="hover"
onClick={(e) => {
session.row_id && setSelectedSessionId(session.row_id);
}}
>
{name}
</BAILink>
);
},
sorter: true,
},
{
key: 'status',
title: t('session.Status'),
dataIndex: 'status',
render: (status: string, session) => {
// @ts-expect-error
return <SessionStatusTag sessionFrgmt={session} />;
},
},
{
key: 'utils',
title: t('session.Utilization'),
},
{
key: 'accelerator',
title: t('session.launcher.AIAccelerator'),
render: (__, session) => {
return (
<SessionOccupiedSlot
// @ts-expect-error
sessionFrgmt={session}
type="accelerator"
/>
);
},
},
{
key: 'cpu',
title: t('session.launcher.CPU'),
render: (__, session) => {
// @ts-expect-error
return <SessionOccupiedSlot sessionFrgmt={session} type="cpu" />;
},
},
{
key: 'mem',
title: t('session.launcher.Memory'),
render: (__, session) => {
// @ts-expect-error
return <SessionOccupiedSlot sessionFrgmt={session} type="mem" />;
},
},
{
key: 'elapsedTime',
title: t('session.ElapsedTime'),
render: (__, session) => {
return (
<SessionReservation
mode="simple-elapsed"
// @ts-expect-error
sessionFrgmt={session}
/>
);
},
},
]}
{...tableProps}
/>
<SessionDetailDrawer
open={!selectedSessionId}
sessionId={selectedSessionId}
onClose={() => {
setSelectedSessionId(undefined);
}}
/>
</>
);
};

export default SessionNodes;
Loading

0 comments on commit d3fe67a

Please sign in to comment.