refactor(usage): split tabs into separate dirs

This commit is contained in:
jialin
2026-06-14 19:14:18 +08:00
committed by jialin
parent 6f56e614f3
commit 6cf512cccd
10 changed files with 49 additions and 44 deletions
@@ -24,8 +24,8 @@ import {
ResourceEventItem,
ResourceEventsResponse
} from '../apis/resource';
import ResourceFilterBar from '../components/resource-filter-bar';
import { parseRollup } from '../utils/time-buckets';
import ResourceFilterBar from './resource-filter-bar';
// Only these four are ever emitted (see resource_event_logger): create/delete
// + the metering-window pair. updated/attached/detached exist as enum values
@@ -279,6 +279,7 @@ const ResourceEvents: React.FC = () => {
columns={columns as any}
style={{ marginTop: 24 }}
pagination={{
size: 'middle',
current: queryParams.page,
pageSize: data?.pagination.perPage ?? 50,
total: data?.pagination.total ?? 0,
+20 -17
View File
@@ -16,11 +16,11 @@
import { useAccess, useIntl } from '@umijs/max';
import { Tabs, TabsProps } from 'antd';
import React, { useMemo, useState } from 'react';
import GpuInstancesTab from './components/gpu-instances-tab';
import ResourceEvents from './components/resource-events';
import StorageTab from './components/storage-tab';
import SummaryTab from './components/summary-tab';
import TokenTab from './components/token-tab';
import ResourceEvents from './events-tab';
import GpuInstancesTab from './instances-tab';
import StorageTab from './storage-tab';
import SummaryTab from './summary-tab';
import TokenTab from './token-tab';
const Usage: React.FC = () => {
const access = useAccess();
@@ -28,11 +28,15 @@ const Usage: React.FC = () => {
// Land on the cross-resource Summary by default.
const [activeKey, setActiveKey] = useState<string>('summary');
const items: TabsProps['items'] = useMemo(
() => [
const items: TabsProps['items'] = useMemo(() => {
type AccessTab = NonNullable<TabsProps['items']>[number] & {
access?: string;
};
const tabs: AccessTab[] = [
{
key: 'summary',
label: intl.formatMessage({ id: 'usage.tabs.summary' }),
access: 'canSeeGpuService',
children: <SummaryTab />
},
{
@@ -43,34 +47,33 @@ const Usage: React.FC = () => {
{
key: 'gpu-instances',
label: intl.formatMessage({ id: 'usage.tabs.gpuInstances' }),
access: 'canSeeGpuService',
children: <GpuInstancesTab />
},
{
key: 'storage',
label: intl.formatMessage({ id: 'usage.tabs.storage' }),
access: 'canSeeGpuService',
children: <StorageTab />
},
{
key: 'resource-events',
label: intl.formatMessage({ id: 'usage.tabs.resourceEvents' }),
access: 'canSeeGpuService',
children: <ResourceEvents />
}
],
[intl]
);
// Users who can't see GPU Service (MaaS-only: no cluster, no resource usage)
// only have token usage — drop the tab shell and show Tokens directly.
if (!access.canSeeGpuService) {
return <TokenTab />;
}
];
return tabs.filter((item) => {
if (!item.access) return true;
return (access as Record<string, boolean>)[item.access];
});
}, [intl, access]);
return (
<Tabs
activeKey={activeKey}
onChange={setActiveKey}
items={items}
destroyOnHidden
// The content area adds 24px top padding; on table pages that space is
// filled immediately, but here it sits empty above the tab bar and reads
// as too tall. Pull the tab bar up to ~flush with the header divider.
@@ -26,6 +26,10 @@ import {
ResourceBreakdownRequest,
ResourceBreakdownResponse
} from '../apis/resource';
import MetricChartCard from '../components/metric-chart-card';
import MetricLabel from '../components/metric-label';
import ResourceExportData from '../components/resource-export-data';
import ResourceFilterBar from '../components/resource-filter-bar';
import useResourceMeta from '../hooks/use-resource-meta';
import { instanceTypeLabel } from '../utils/format-instance-type';
import {
@@ -35,10 +39,6 @@ import {
parseRollup
} from '../utils/time-buckets';
import { buildTrendSeries } from '../utils/trend-series';
import MetricChartCard from './metric-chart-card';
import MetricLabel from './metric-label';
import ResourceExportData from './resource-export-data';
import ResourceFilterBar from './resource-filter-bar';
type Scope = 'self' | 'all';
type Metric = 'gpu_hours' | 'instance_hours';
@@ -24,6 +24,10 @@ import {
ResourceBreakdownRequest,
ResourceBreakdownResponse
} from '../apis/resource';
import MetricChartCard from '../components/metric-chart-card';
import MetricLabel from '../components/metric-label';
import ResourceExportData from '../components/resource-export-data';
import ResourceFilterBar from '../components/resource-filter-bar';
import useResourceMeta from '../hooks/use-resource-meta';
import {
bucketKey,
@@ -32,10 +36,6 @@ import {
parseRollup
} from '../utils/time-buckets';
import { buildTrendSeries } from '../utils/trend-series';
import MetricChartCard from './metric-chart-card';
import MetricLabel from './metric-label';
import ResourceExportData from './resource-export-data';
import ResourceFilterBar from './resource-filter-bar';
type Scope = 'self' | 'all';
type Metric = 'storage_gb_days' | 'storage_gb_hours';
@@ -500,6 +500,7 @@ const StorageTab: React.FC = () => {
}
}}
pagination={{
size: 'middle',
current: tablePage,
pageSize: tableData?.pagination.perPage ?? 50,
total: tableData?.pagination.total ?? 0,
@@ -38,13 +38,13 @@ import {
ResourceBreakdownResponse,
UsageSummaryResponse
} from '../apis/resource';
import ResourceFilterBar from '../components/resource-filter-bar';
import useResourceMeta from '../hooks/use-resource-meta';
import {
bucketKey,
generateBucketRange,
Granularity
} from '../utils/time-buckets';
import ResourceFilterBar from './resource-filter-bar';
type Scope = 'self' | 'all';
@@ -1,7 +1,7 @@
import { useIntl } from '@umijs/max';
import { Tabs } from 'antd';
import React, { useMemo } from 'react';
import { UsageFilterItem } from '../config/types';
import { UsageFilterItem } from '../../config/types';
import ApiKeysTable from '../tables/apikeys-table';
import ModelsTable from '../tables/models-table';
import UsersTable from '../tables/users-table';
@@ -3,13 +3,13 @@ import { formatLargeNumber } from '@/utils';
import { SimpleCard } from '@gpustack/core-ui';
import { useAccess, useIntl } from '@umijs/max';
import React, { useEffect, useMemo, useState } from 'react';
import DailyUsage from '../components/daily-usage';
import ExportData from '../components/export-data';
import FilterBar from '../components/filter-bar';
import useExportTable from '../hooks/use-export-table';
import { useUsageFilters } from '../hooks/use-usage-filters';
import useQueryUsageMetaData from '../services/use-query-meta-data';
import BreakdownTabs from './breakdown-tabs';
import DailyUsage from './daily-usage';
import ExportData from './export-data';
import FilterBar from './filter-bar';
import BreakdownTabs from './components/breakdown-tabs';
type DateType = 'date' | 'week' | 'month' | 'quarter' | 'year';
@@ -5,10 +5,10 @@ import { useIntl } from '@umijs/max';
import { Table } from 'antd';
import _ from 'lodash';
import { useEffect, useRef, useState } from 'react';
import { FilterOptionType } from '../config/types';
import useAPIKeys from '../hooks/use-apikeys-columns';
import useQueryBreakdownList from '../services/use-query-breakdown-list';
import getBreakdownRowKey from '../utils/get-breakdown-row-key';
import { FilterOptionType } from '../../config/types';
import useAPIKeys from '../../hooks/use-apikeys-columns';
import useQueryBreakdownList from '../../services/use-query-breakdown-list';
import getBreakdownRowKey from '../../utils/get-breakdown-row-key';
const APIKeys: React.FC<{
apiKeys: FilterOptionType[];
@@ -6,10 +6,10 @@ import { useIntl } from '@umijs/max';
import { Table } from 'antd';
import _ from 'lodash';
import { useEffect, useMemo, useRef, useState } from 'react';
import { BreakdownItem, FilterOptionType } from '../config/types';
import useModelsColumns from '../hooks/use-models-columns';
import useQueryBreakdownList from '../services/use-query-breakdown-list';
import getBreakdownRowKey from '../utils/get-breakdown-row-key';
import { BreakdownItem, FilterOptionType } from '../../config/types';
import useModelsColumns from '../../hooks/use-models-columns';
import useQueryBreakdownList from '../../services/use-query-breakdown-list';
import getBreakdownRowKey from '../../utils/get-breakdown-row-key';
const Models: React.FC<{
routes: FilterOptionType[];
@@ -5,10 +5,10 @@ import { useIntl } from '@umijs/max';
import { Table } from 'antd';
import _ from 'lodash';
import { useEffect, useRef, useState } from 'react';
import { FilterOptionType } from '../config/types';
import useUsersColumns from '../hooks/use-users-columns';
import useQueryBreakdownList from '../services/use-query-breakdown-list';
import getBreakdownRowKey from '../utils/get-breakdown-row-key';
import { FilterOptionType } from '../../config/types';
import useUsersColumns from '../../hooks/use-users-columns';
import useQueryBreakdownList from '../../services/use-query-breakdown-list';
import getBreakdownRowKey from '../../utils/get-breakdown-row-key';
const Users: React.FC<{
users: FilterOptionType[];