refactor(tables): share parent column grid in expandable child rows

- llmodels/model-routes/cluster child rows use ExpandedRowGrid + Cell
  (auto-flow spans, no parent-key/grid-line math)
- define --seal-table-row-min-height token in global.less
- routes created_at column: span -> fixed width 180
This commit is contained in:
jialin
2026-07-16 13:09:18 +08:00
committed by jialin
parent 938aef6c26
commit 67e2d914f4
10 changed files with 255 additions and 212 deletions
@@ -1,6 +1,5 @@
import { ListItem as WorkerListItem } from '@/pages/resources/config/types';
import { AutoTooltip, RowChildren } from '@gpustack/core-ui';
import { Col, Row } from 'antd';
import { AutoTooltip, ExpandedRowGrid } from '@gpustack/core-ui';
import dayjs from 'dayjs';
import React from 'react';
import { ModelInstanceListItem } from '../../config/types';
@@ -11,11 +10,17 @@ import DistributeInfoCell from '../instance-cells/distribute-info-cell';
import DownloadingStatusCell from '../instance-cells/downloading-status-cell';
import InstanceStatusCell from '../instance-cells/instance-status-cell';
import NameCell from '../instance-cells/name-cell';
interface InstanceItemProps {
instanceData: ModelInstanceListItem;
workerList: WorkerListItem[];
modelData?: any;
defaultOpenId: string;
// Column grid shared from the parent SealTable so this child row aligns
// its cells to the parent columns instead of guessing paddings.
gridTemplate?: string;
prefixWidth?: number;
columns?: any[];
handleChildSelect: (val: string, item: ModelInstanceListItem) => void;
}
@@ -24,79 +29,67 @@ const InstanceItem: React.FC<InstanceItemProps> = ({
workerList,
modelData,
defaultOpenId,
gridTemplate,
prefixWidth = 0,
columns,
handleChildSelect
}) => {
// The child row shares the parent's column grid; cells flow left-to-right and
// only declare a span, so there is no dependency on parent column keys.
// Parent layout: name (1) | middle plugin/source region | replicas,
// created_at, operation (last 3). The middle absorbs whatever columns sit
// between name and replicas (cluster_id, source, any plugin column).
const columnCount = columns?.length ?? 0;
const middleSpan = Math.max(columnCount - 4, 1);
return (
<div style={{ borderRadius: 'var(--ant-table-header-border-radius)' }}>
<RowChildren>
<Row
style={{ width: '100%', color: 'var(--ant-color-text-secondary)' }}
align="middle"
>
<Col
span={6}
style={{
paddingInline: 'var(--ant-table-cell-padding-inline)'
}}
>
<NameCell
record={instanceData}
modelData={modelData}
defaultOpenId={defaultOpenId}
></NameCell>
</Col>
<Col span={7}>
<span
style={{
paddingLeft: '58px',
flexWrap: 'wrap',
gap: '8px'
}}
className="flex align-center"
>
<CPUOffloadingCell record={instanceData}></CPUOffloadingCell>
<DistributeInfoCell
record={instanceData}
workerList={workerList}
></DistributeInfoCell>
</span>
</Col>
<Col span={4}>
<span
style={{ paddingLeft: '40px', gap: 4 }}
className="flex-center"
>
<InstanceStatusCell
record={instanceData}
onSelect={handleChildSelect}
/>
<DownloadingStatusCell
backend={modelData?.backend}
distributed_servers={instanceData.distributed_servers}
workerList={workerList}
record={instanceData}
></DownloadingStatusCell>
</span>
</Col>
<Col span={4}>
<span style={{ paddingLeft: 43 }} className="flex">
<AutoTooltip ghost>
{dayjs(instanceData.created_at).format('YYYY-MM-DD HH:mm:ss')}
</AutoTooltip>
</span>
</Col>
<Col span={3}>
<div style={{ paddingLeft: 36 }}>
<ActionsCell
record={instanceData}
modelData={modelData}
onSelect={handleChildSelect}
></ActionsCell>
</div>
</Col>
</Row>
</RowChildren>
</div>
<ExpandedRowGrid
gridTemplate={gridTemplate}
prefixWidth={prefixWidth}
style={{ color: 'var(--ant-color-text-secondary)' }}
>
<ExpandedRowGrid.Cell span={1}>
<NameCell
record={instanceData}
modelData={modelData}
defaultOpenId={defaultOpenId}
></NameCell>
</ExpandedRowGrid.Cell>
<ExpandedRowGrid.Cell
span={middleSpan}
style={{ flexWrap: 'wrap', gap: 8 }}
>
<CPUOffloadingCell record={instanceData}></CPUOffloadingCell>
<DistributeInfoCell
record={instanceData}
workerList={workerList}
></DistributeInfoCell>
</ExpandedRowGrid.Cell>
<ExpandedRowGrid.Cell span={1} style={{ gap: 4 }}>
<InstanceStatusCell
record={instanceData}
onSelect={handleChildSelect}
/>
<DownloadingStatusCell
backend={modelData?.backend}
distributed_servers={instanceData.distributed_servers}
workerList={workerList}
record={instanceData}
></DownloadingStatusCell>
</ExpandedRowGrid.Cell>
<ExpandedRowGrid.Cell span={1}>
<AutoTooltip ghost>
{dayjs(instanceData.created_at).format('YYYY-MM-DD HH:mm:ss')}
</AutoTooltip>
</ExpandedRowGrid.Cell>
<ExpandedRowGrid.Cell span={1}>
<ActionsCell
record={instanceData}
modelData={modelData}
onSelect={handleChildSelect}
></ActionsCell>
</ExpandedRowGrid.Cell>
</ExpandedRowGrid>
);
};
export default InstanceItem;
@@ -17,6 +17,9 @@ interface InstanceItemProps {
workerList: WorkerListItem[];
modelData?: any;
currentExpanded?: string;
gridTemplate?: string;
prefixWidth?: number;
columns?: any[];
handleChildSelect: (val: string, item: ModelInstanceListItem) => void;
}
@@ -25,6 +28,9 @@ const Instances: React.FC<InstanceItemProps> = ({
workerList,
modelData,
currentExpanded,
gridTemplate,
prefixWidth,
columns,
handleChildSelect
}) => {
const [firstLoad, setFirstLoad] = React.useState(true);
@@ -55,6 +61,9 @@ const Instances: React.FC<InstanceItemProps> = ({
instanceData={item}
defaultOpenId={firstLoad ? defaultOpenId : ''}
handleChildSelect={handleChildSelect}
gridTemplate={gridTemplate}
prefixWidth={prefixWidth}
columns={columns}
></InstanceItem>
);
})}
@@ -441,6 +441,9 @@ const Models: React.FC<ModelsProps> = ({
modelData={options.parent}
workerList={workerList}
handleChildSelect={handleChildSelect}
gridTemplate={options.gridTemplate}
prefixWidth={options.prefixWidth}
columns={options.columns}
></Instances>
);
},