style(usage): unify name column header + DeletedTag across breakdown tables
This commit is contained in:
@@ -64,6 +64,10 @@ export interface ResourceBreakdownItem extends ResourceBreakdownSummary {
|
||||
volume_name?: string;
|
||||
user_id?: number;
|
||||
user_name?: string;
|
||||
// The grouped entity (instance / volume / user) no longer exists. The name
|
||||
// fields keep the clean (stale) name; the tables show a DeletedTag off this
|
||||
// flag plus the id, matching the Tokens tab.
|
||||
deleted?: boolean;
|
||||
// Grouped-trend rows carry the sub-group label (sku / instance / user / …)
|
||||
// alongside ``date`` so the chart can pivot one series per group.
|
||||
group?: string;
|
||||
@@ -277,12 +281,16 @@ function flattenItem(
|
||||
};
|
||||
if (it.date) flat.date = it.date;
|
||||
const id = it.id ?? undefined;
|
||||
// Deleted entities get a "(Deleted)" suffix, matching the Token breakdown.
|
||||
const deleted = !!it.deleted;
|
||||
const rawKey = it.key ?? undefined;
|
||||
const key = it.deleted && rawKey != null ? `${rawKey} (Deleted)` : rawKey;
|
||||
// The chart series legend keeps the "(Deleted)" suffix (a legend can't render
|
||||
// a tag); the tables show a DeletedTag off ``flat.deleted`` + the id and so
|
||||
// use the clean name.
|
||||
const key = deleted && rawKey != null ? `${rawKey} (Deleted)` : rawKey;
|
||||
// Generic group label — for a compound (date + dim) trend row the key is the
|
||||
// sub-group value (the switch below targets single-dimension table rows).
|
||||
if (rawKey != null) flat.group = key;
|
||||
flat.deleted = deleted;
|
||||
switch (groupBy) {
|
||||
case 'resource_type':
|
||||
flat.resource_type = key;
|
||||
@@ -292,15 +300,15 @@ function flattenItem(
|
||||
flat.gpu_type = key;
|
||||
break;
|
||||
case 'instance':
|
||||
flat.instance_name = key;
|
||||
flat.instance_name = rawKey;
|
||||
flat.instance_id = id;
|
||||
break;
|
||||
case 'volume':
|
||||
flat.volume_name = key;
|
||||
flat.volume_name = rawKey;
|
||||
flat.volume_id = id;
|
||||
break;
|
||||
case 'user':
|
||||
flat.user_name = key;
|
||||
flat.user_name = rawKey;
|
||||
flat.user_id = id;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -32,7 +32,7 @@ const DeletedTag: React.FC<DeletedTagProps> = ({ id }) => {
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
{id != null && (
|
||||
{!!id && (
|
||||
<span className="text-tertiary">
|
||||
<span style={{ margin: '0 2px' }}>·</span>#{id}
|
||||
</span>
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
// columns.ts
|
||||
import { AutoTooltip } from '@gpustack/core-ui';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Tag } from 'antd';
|
||||
import { useMemo } from 'react';
|
||||
import DeletedTag from '../components/deleted-tag';
|
||||
import { BreakdownItem as ListItem } from '../config/types';
|
||||
|
||||
const useModelsColumns = (): Array<{
|
||||
title: string;
|
||||
dataIndex: string | string[];
|
||||
key: string;
|
||||
}> => {
|
||||
const useModelsColumns = () => {
|
||||
const intl = useIntl();
|
||||
|
||||
return useMemo(() => {
|
||||
@@ -19,23 +15,18 @@ const useModelsColumns = (): Array<{
|
||||
dataIndex: ['api_key', 'identity', 'value', 'api_key_name'],
|
||||
key: 'api_key_name',
|
||||
render: (text: string, record: ListItem) => (
|
||||
<span className="flex items-center">
|
||||
<span className="flex items-center gap-8">
|
||||
<AutoTooltip ghost title={<span>{text}</span>}>
|
||||
<span className="text-primary">{text}</span>
|
||||
<span
|
||||
className={
|
||||
record.api_key?.deleted ? 'text-tertiary' : 'text-primary'
|
||||
}
|
||||
>
|
||||
{text}
|
||||
</span>
|
||||
</AutoTooltip>
|
||||
{record.api_key?.deleted && (
|
||||
<Tag
|
||||
style={{
|
||||
marginLeft: 8,
|
||||
borderRadius: 12,
|
||||
color: 'var(--ant-color-text-tertiary)',
|
||||
borderColor: 'var(--ant-color-split)',
|
||||
backgroundColor: 'transparent'
|
||||
}}
|
||||
variant="outlined"
|
||||
>
|
||||
{intl.formatMessage({ id: 'usage.table.deleted' })}
|
||||
</Tag>
|
||||
<DeletedTag id={record.api_key?.identity?.current?.api_key_id} />
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
import { getGPUStackPlugin } from '@/plugins';
|
||||
import { AutoTooltip } from '@gpustack/core-ui';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Tag } from 'antd';
|
||||
import { useMemo } from 'react';
|
||||
import DeletedTag from '../components/deleted-tag';
|
||||
import { BreakdownItem as ListItem } from '../config/types';
|
||||
|
||||
// Plugin slot: enterprise plugins can contribute extra columns to the
|
||||
@@ -51,27 +51,22 @@ const useModelsColumns = (): ColumnDef[] => {
|
||||
dataIndex: ['route', 'label'],
|
||||
key: 'route_name',
|
||||
render: (text: string, record: ListItem) => (
|
||||
<span className="flex items-center">
|
||||
<span className="flex items-center gap-8">
|
||||
<AutoTooltip
|
||||
ghost
|
||||
style={{ maxWidth: 400 }}
|
||||
title={<span>{text}</span>}
|
||||
>
|
||||
<span className="text-primary">{text}</span>
|
||||
<span
|
||||
className={
|
||||
record.route?.deleted ? 'text-tertiary' : 'text-primary'
|
||||
}
|
||||
>
|
||||
{text}
|
||||
</span>
|
||||
</AutoTooltip>
|
||||
{record.route?.deleted && (
|
||||
<Tag
|
||||
style={{
|
||||
marginLeft: 8,
|
||||
borderRadius: 12,
|
||||
color: 'var(--ant-color-text-tertiary)',
|
||||
borderColor: 'var(--ant-color-split)',
|
||||
backgroundColor: 'transparent'
|
||||
}}
|
||||
variant="outlined"
|
||||
>
|
||||
{intl.formatMessage({ id: 'usage.table.deleted' })}
|
||||
</Tag>
|
||||
<DeletedTag id={record.route?.identity?.current?.route_id} />
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
// columns.ts
|
||||
import { AutoTooltip } from '@gpustack/core-ui';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Tag } from 'antd';
|
||||
import { useMemo } from 'react';
|
||||
import DeletedTag from '../components/deleted-tag';
|
||||
import { BreakdownItem as ListItem } from '../config/types';
|
||||
|
||||
interface ColumnsHookProps {
|
||||
sortOrder: string[];
|
||||
}
|
||||
|
||||
const useModelsColumns = (): Array<{
|
||||
title: string;
|
||||
dataIndex: string | string[];
|
||||
key: string;
|
||||
}> => {
|
||||
const useModelsColumns = () => {
|
||||
const intl = useIntl();
|
||||
|
||||
return useMemo(() => {
|
||||
@@ -23,27 +19,22 @@ const useModelsColumns = (): Array<{
|
||||
dataIndex: ['user', 'identity', 'value', 'user_name'],
|
||||
key: 'user_name',
|
||||
render: (text: string, record: ListItem) => (
|
||||
<span className="flex items-center">
|
||||
<span className="flex items-center gap-8">
|
||||
<AutoTooltip
|
||||
ghost
|
||||
style={{ maxWidth: 400 }}
|
||||
title={<span>{text}</span>}
|
||||
>
|
||||
<span className="text-primary">{text}</span>
|
||||
<span
|
||||
className={
|
||||
record.user?.deleted ? 'text-tertiary' : 'text-primary'
|
||||
}
|
||||
>
|
||||
{text}
|
||||
</span>
|
||||
</AutoTooltip>
|
||||
{record.user?.deleted && (
|
||||
<Tag
|
||||
style={{
|
||||
marginLeft: 8,
|
||||
borderRadius: 12,
|
||||
color: 'var(--ant-color-text-tertiary)',
|
||||
borderColor: 'var(--ant-color-split)',
|
||||
backgroundColor: 'transparent'
|
||||
}}
|
||||
variant="outlined"
|
||||
>
|
||||
{intl.formatMessage({ id: 'usage.table.deleted' })}
|
||||
</Tag>
|
||||
<DeletedTag id={record.user?.identity?.current?.user_id} />
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
|
||||
@@ -2,9 +2,11 @@ import {
|
||||
buildInstanceTypeRecordFromMiB,
|
||||
renderInstanceType
|
||||
} from '@/pages/gpu-service/instances/utils/render-instance-type';
|
||||
import { AutoTooltip } from '@gpustack/core-ui';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { useMemo } from 'react';
|
||||
import { ResourceBreakdownItem } from '../../apis/resource';
|
||||
import DeletedTag from '../../components/deleted-tag';
|
||||
import { instanceTypeSeriesLabel } from '../../utils/format-instance-type';
|
||||
import { parseRollup } from '../../utils/time-buckets';
|
||||
|
||||
@@ -108,6 +110,22 @@ const useInstancesColumns = (groupKey: GroupKey) => {
|
||||
key: 'last_active',
|
||||
render: (v?: string) => (v ? parseRollup(v).format('YYYY-MM-DD') : '-')
|
||||
};
|
||||
// Name cell with a DeletedTag when the entity no longer exists — mirrors the
|
||||
// Tokens tab. The id keeps two deleted rows sharing a stale name distinct.
|
||||
const renderName = (text: string, id?: number, deleted?: boolean) => (
|
||||
<span className="flex items-center gap-8">
|
||||
<AutoTooltip
|
||||
ghost
|
||||
style={{
|
||||
maxWidth: 400,
|
||||
...(deleted ? { color: 'var(--ant-color-text-tertiary)' } : null)
|
||||
}}
|
||||
>
|
||||
{text || '-'}
|
||||
</AutoTooltip>
|
||||
{deleted && <DeletedTag id={id ?? null} />}
|
||||
</span>
|
||||
);
|
||||
if (groupKey === 'gpu_type') {
|
||||
return [
|
||||
instanceTypeColType,
|
||||
@@ -123,9 +141,11 @@ const useInstancesColumns = (groupKey: GroupKey) => {
|
||||
if (groupKey === 'instance') {
|
||||
return [
|
||||
{
|
||||
title: intl.formatMessage({ id: 'usage.table.instance' }),
|
||||
title: intl.formatMessage({ id: 'common.table.name' }),
|
||||
dataIndex: 'instance_name',
|
||||
key: 'instance_name'
|
||||
key: 'instance_name',
|
||||
render: (text: string, row: ResourceBreakdownItem) =>
|
||||
renderName(text, row.instance_id, row.deleted)
|
||||
},
|
||||
instanceTypeColInstance,
|
||||
...baseValueCols,
|
||||
@@ -135,9 +155,11 @@ const useInstancesColumns = (groupKey: GroupKey) => {
|
||||
// user tab
|
||||
return [
|
||||
{
|
||||
title: intl.formatMessage({ id: 'usage.table.user' }),
|
||||
title: intl.formatMessage({ id: 'common.table.name' }),
|
||||
dataIndex: 'user_name',
|
||||
key: 'user_name'
|
||||
key: 'user_name',
|
||||
render: (text: string, row: ResourceBreakdownItem) =>
|
||||
renderName(text, row.user_id, row.deleted)
|
||||
},
|
||||
...baseValueCols,
|
||||
lastActiveCol
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { AutoTooltip } from '@gpustack/core-ui';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { useMemo } from 'react';
|
||||
import { ResourceBreakdownItem } from '../../apis/resource';
|
||||
import DeletedTag from '../../components/deleted-tag';
|
||||
import { parseRollup } from '../../utils/time-buckets';
|
||||
|
||||
type GroupKey = 'volume' | 'user';
|
||||
@@ -39,12 +41,30 @@ const useStorageColumns = (groupKey: GroupKey) => {
|
||||
key: 'last_active',
|
||||
render: (v?: string) => (v ? parseRollup(v).format('YYYY-MM-DD') : '-')
|
||||
};
|
||||
// Name cell with a DeletedTag when the entity no longer exists — mirrors the
|
||||
// Tokens tab. The id keeps two deleted rows sharing a stale name distinct.
|
||||
const renderName = (text: string, id?: number, deleted?: boolean) => (
|
||||
<span className="flex items-center gap-8">
|
||||
<AutoTooltip
|
||||
ghost
|
||||
style={{
|
||||
maxWidth: 400,
|
||||
...(deleted ? { color: 'var(--ant-color-text-tertiary)' } : null)
|
||||
}}
|
||||
>
|
||||
{text || '-'}
|
||||
</AutoTooltip>
|
||||
{deleted && <DeletedTag id={id ?? null} />}
|
||||
</span>
|
||||
);
|
||||
if (groupKey === 'volume') {
|
||||
return [
|
||||
{
|
||||
title: intl.formatMessage({ id: 'usage.tabs.storage' }),
|
||||
title: intl.formatMessage({ id: 'common.table.name' }),
|
||||
dataIndex: 'volume_name',
|
||||
key: 'volume_name'
|
||||
key: 'volume_name',
|
||||
render: (text: string, row: ResourceBreakdownItem) =>
|
||||
renderName(text, row.volume_id, row.deleted)
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: 'usage.table.type' }),
|
||||
@@ -65,9 +85,11 @@ const useStorageColumns = (groupKey: GroupKey) => {
|
||||
}
|
||||
return [
|
||||
{
|
||||
title: intl.formatMessage({ id: 'usage.table.user' }),
|
||||
title: intl.formatMessage({ id: 'common.table.name' }),
|
||||
dataIndex: 'user_name',
|
||||
key: 'user_name'
|
||||
key: 'user_name',
|
||||
render: (text: string, row: ResourceBreakdownItem) =>
|
||||
renderName(text, row.user_id, row.deleted)
|
||||
},
|
||||
...valueCols,
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user