style: card style
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { Tabs } from 'antd';
|
||||
import React from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import { GroupOption } from '../config';
|
||||
import { UsageFilterItem } from '../config/types';
|
||||
import ApiKeysTable from '../tables/apikeys-table';
|
||||
@@ -8,6 +8,7 @@ import UsersTable from '../tables/users-table';
|
||||
|
||||
type FilterOptionType = Omit<UsageFilterItem, 'label' | 'deleted'>;
|
||||
type GroupOptionType = GroupOption<UsageFilterItem>;
|
||||
const EMPTY_FILTERS: FilterOptionType[] = [];
|
||||
|
||||
const BreakdownTabs: React.FC<{
|
||||
dateRange: {
|
||||
@@ -15,58 +16,68 @@ const BreakdownTabs: React.FC<{
|
||||
end_date: string;
|
||||
};
|
||||
scope: string;
|
||||
refreshKey?: number;
|
||||
filters: {
|
||||
models?: FilterOptionType[];
|
||||
users?: FilterOptionType[];
|
||||
api_keys?: FilterOptionType[];
|
||||
};
|
||||
}> = ({ filters, dateRange, scope }) => {
|
||||
const items = [
|
||||
{
|
||||
key: 'models',
|
||||
label: 'Models',
|
||||
forceRender: true,
|
||||
children: (
|
||||
<ModelsTable
|
||||
key="models"
|
||||
models={filters.models || []}
|
||||
dateRange={dateRange}
|
||||
scope={scope}
|
||||
/>
|
||||
)
|
||||
},
|
||||
{
|
||||
key: 'users',
|
||||
label: 'Users',
|
||||
forceRender: true,
|
||||
children: (
|
||||
<UsersTable
|
||||
key="users"
|
||||
users={filters.users || []}
|
||||
dateRange={dateRange}
|
||||
scope={scope}
|
||||
/>
|
||||
)
|
||||
},
|
||||
{
|
||||
key: 'api_keys',
|
||||
label: 'API Keys',
|
||||
forceRender: true,
|
||||
children: (
|
||||
<ApiKeysTable
|
||||
key="api_keys"
|
||||
apiKeys={filters.api_keys || []}
|
||||
dateRange={dateRange}
|
||||
scope={scope}
|
||||
/>
|
||||
)
|
||||
}
|
||||
].filter((item) => {
|
||||
if (item.key === 'users') {
|
||||
return scope === 'all';
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}> = ({ filters, dateRange, scope, refreshKey = 0 }) => {
|
||||
const models = filters.models || EMPTY_FILTERS;
|
||||
const users = filters.users || EMPTY_FILTERS;
|
||||
const apiKeys = filters.api_keys || EMPTY_FILTERS;
|
||||
|
||||
const items = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
key: 'models',
|
||||
label: 'Models',
|
||||
forceRender: true,
|
||||
children: (
|
||||
<ModelsTable
|
||||
key="models"
|
||||
models={models}
|
||||
dateRange={dateRange}
|
||||
scope={scope}
|
||||
refreshKey={refreshKey}
|
||||
/>
|
||||
)
|
||||
},
|
||||
{
|
||||
key: 'users',
|
||||
label: 'Users',
|
||||
forceRender: true,
|
||||
children: (
|
||||
<UsersTable
|
||||
key="users"
|
||||
users={users}
|
||||
dateRange={dateRange}
|
||||
scope={scope}
|
||||
refreshKey={refreshKey}
|
||||
/>
|
||||
)
|
||||
},
|
||||
{
|
||||
key: 'api_keys',
|
||||
label: 'API Keys',
|
||||
forceRender: true,
|
||||
children: (
|
||||
<ApiKeysTable
|
||||
key="api_keys"
|
||||
apiKeys={apiKeys}
|
||||
dateRange={dateRange}
|
||||
scope={scope}
|
||||
refreshKey={refreshKey}
|
||||
/>
|
||||
)
|
||||
}
|
||||
].filter((item) => {
|
||||
if (item.key === 'users') {
|
||||
return scope === 'all';
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}, [apiKeys, dateRange, models, refreshKey, scope, users]);
|
||||
|
||||
return (
|
||||
<div style={{ marginTop: 16 }}>
|
||||
|
||||
@@ -2,7 +2,6 @@ import CardWrapper from '@/components/card-wrapper';
|
||||
import MixLineBar from '@/components/echarts/mix-line-bar';
|
||||
import BaseSelect from '@/components/seal-form/base/select';
|
||||
import { baseColorMap } from '@/pages/dashboard/config';
|
||||
import { formatLargeNumber } from '@/utils';
|
||||
import { Segmented } from 'antd';
|
||||
import dayjs from 'dayjs';
|
||||
import React, { useMemo } from 'react';
|
||||
@@ -31,10 +30,10 @@ const ControlLabel = styled.span`
|
||||
interface DailyUsageProps {
|
||||
timeSeriesData: TimeSeriesData | null;
|
||||
metric: string;
|
||||
groupBy: string;
|
||||
groupBy: string | null;
|
||||
granularity: string;
|
||||
onMetricChange: (value: string) => void;
|
||||
onGroupByChange: (value: string) => void;
|
||||
onGroupByChange: (value: string | null) => void;
|
||||
onGranularityChange: (value: string) => void;
|
||||
}
|
||||
|
||||
@@ -53,49 +52,6 @@ const DailyUsage: React.FC<DailyUsageProps> = (props) => {
|
||||
onGranularityChange
|
||||
} = props;
|
||||
|
||||
const summary = timeSeriesData?.summary || {
|
||||
input_tokens: 0,
|
||||
output_tokens: 0,
|
||||
total_tokens: 0,
|
||||
api_requests: 0,
|
||||
models_called: 0
|
||||
};
|
||||
|
||||
const summaryCards = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
label: formatLargeNumber(summary.input_tokens) as string,
|
||||
value: 'Input tokens',
|
||||
color: baseColorMap.baseR3,
|
||||
iconType: 'roundRect'
|
||||
},
|
||||
{
|
||||
label: formatLargeNumber(summary.output_tokens) as string,
|
||||
value: 'Output tokens',
|
||||
color: baseColorMap.base,
|
||||
iconType: 'roundRect'
|
||||
},
|
||||
{
|
||||
label: formatLargeNumber(summary.total_tokens) as string,
|
||||
value: 'Total tokens',
|
||||
color: baseColorMap.baseL1,
|
||||
iconType: 'roundRect'
|
||||
},
|
||||
{
|
||||
label: formatLargeNumber(summary.api_requests) as string,
|
||||
value: 'API requests',
|
||||
color: baseColorMap.baseR1,
|
||||
iconType: 'circle'
|
||||
},
|
||||
{
|
||||
label: summary.models_called.toString(),
|
||||
value: 'Models used',
|
||||
color: baseColorMap.baseR2,
|
||||
iconType: 'roundRect'
|
||||
}
|
||||
];
|
||||
}, [summary]);
|
||||
|
||||
const { chartData, xAxisData } = useMemo(() => {
|
||||
if (!timeSeriesData?.series || timeSeriesData.series.length === 0) {
|
||||
return { chartData: { line: [], bar: [] }, xAxisData: [] };
|
||||
@@ -120,17 +76,10 @@ const DailyUsage: React.FC<DailyUsageProps> = (props) => {
|
||||
}));
|
||||
|
||||
// API requests use line chart, tokens use bar chart
|
||||
if (metric === 'api_requests') {
|
||||
return {
|
||||
chartData: { line: chartSeries, bar: [] },
|
||||
xAxisData: xAxis
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
chartData: { line: [], bar: chartSeries },
|
||||
xAxisData: xAxis
|
||||
};
|
||||
}
|
||||
return {
|
||||
chartData: { line: [], bar: chartSeries },
|
||||
xAxisData: xAxis
|
||||
};
|
||||
}, [timeSeriesData, metric]);
|
||||
|
||||
const legendData = useMemo(() => {
|
||||
@@ -142,6 +91,10 @@ const DailyUsage: React.FC<DailyUsageProps> = (props) => {
|
||||
}));
|
||||
}, [timeSeriesData, metric]);
|
||||
|
||||
const handleOnGroupByChange = (value: string) => {
|
||||
onGroupByChange(value || null);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<CardWrapper style={{ width: '100%', marginTop: 20 }}>
|
||||
@@ -154,16 +107,18 @@ const DailyUsage: React.FC<DailyUsageProps> = (props) => {
|
||||
value={metric}
|
||||
popupMatchSelectWidth={false}
|
||||
onChange={onMetricChange}
|
||||
style={{ width: 180 }}
|
||||
style={{ width: 'max-content' }}
|
||||
/>
|
||||
|
||||
<BaseSelect
|
||||
allowClear
|
||||
variant="borderless"
|
||||
prefix={<ControlLabel>Group by</ControlLabel>}
|
||||
options={groupByOptions}
|
||||
value={groupBy}
|
||||
popupMatchSelectWidth={false}
|
||||
onChange={onGroupByChange}
|
||||
onChange={handleOnGroupByChange}
|
||||
style={{ width: 'max-content' }}
|
||||
/>
|
||||
</div>
|
||||
<Segmented
|
||||
@@ -173,8 +128,6 @@ const DailyUsage: React.FC<DailyUsageProps> = (props) => {
|
||||
onChange={onGranularityChange}
|
||||
></Segmented>
|
||||
</ControlsWrapper>
|
||||
|
||||
{/* <SimpleCard dataList={summaryCards} height={80} /> */}
|
||||
<MixLineBar
|
||||
chartData={chartData}
|
||||
seriesData={[]}
|
||||
|
||||
@@ -1,36 +1,88 @@
|
||||
import AutoTooltip from '@/components/auto-tooltip';
|
||||
import ModalFooter from '@/components/modal-footer';
|
||||
import ScrollerModal from '@/components/scroller-modal';
|
||||
import { exportJsonToExcel } from '@/utils/excel-reader';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Table, TableColumnType } from 'antd';
|
||||
import React, { useEffect } from 'react';
|
||||
import { useUsageFilters } from '../hooks/use-usage-filters';
|
||||
import useQueryBreakdownList from '../services/use-query-breakdown-list';
|
||||
import getBreakdownRowKey from '../utils/get-breakdown-row-key';
|
||||
import FilterBar from './filter-bar';
|
||||
|
||||
type DateType = 'date' | 'week' | 'month' | 'quarter' | 'year';
|
||||
type ValueType = string | number | null;
|
||||
|
||||
const ExportData: React.FC<{
|
||||
open: boolean;
|
||||
onCancel: () => void;
|
||||
initialScope: string;
|
||||
metaData: any;
|
||||
granularity: string;
|
||||
initialState: {
|
||||
activeModels: ValueType[][];
|
||||
activeApiKeys: ValueType[][];
|
||||
};
|
||||
|
||||
handlePickerChange: (picker: DateType) => void;
|
||||
}> = (props) => {
|
||||
const { open, onCancel, initialScope, metaData } = props || {};
|
||||
const {
|
||||
open,
|
||||
onCancel,
|
||||
initialScope,
|
||||
metaData,
|
||||
granularity,
|
||||
handlePickerChange,
|
||||
initialState
|
||||
} = props || {};
|
||||
const intl = useIntl();
|
||||
|
||||
const {
|
||||
filters,
|
||||
commonFilters,
|
||||
fetchData,
|
||||
loading,
|
||||
timeSeriesData,
|
||||
filterBar
|
||||
} = useUsageFilters({
|
||||
initialScope: initialScope,
|
||||
metaData,
|
||||
chartFilters: {},
|
||||
summaryColumns: {}
|
||||
const [pageParams, setPageParams] = React.useState<{
|
||||
page: number;
|
||||
perPage: number;
|
||||
}>({
|
||||
page: 1,
|
||||
perPage: 100
|
||||
});
|
||||
|
||||
const exportTableColumns: TableColumnType[] = [
|
||||
const {
|
||||
fetchData: fetchExportData,
|
||||
loading,
|
||||
dataSource,
|
||||
cancelRequest
|
||||
} = useQueryBreakdownList({
|
||||
key: 'exportTableData'
|
||||
});
|
||||
|
||||
const { filters, commonFilters, filterBar } = useUsageFilters({
|
||||
initialScope: initialScope,
|
||||
metaData,
|
||||
chartFilters: {
|
||||
metric: 'total_tokens',
|
||||
group_by: null,
|
||||
granularity: props.granularity || 'day'
|
||||
},
|
||||
initialState: initialState,
|
||||
summaryColumns: [],
|
||||
autoFetchOnFilterChange: true,
|
||||
onFetchData: ({
|
||||
chartFilters: nextChartFilters,
|
||||
filters: nextFilters,
|
||||
commonFilters: nextCommonFilters
|
||||
}) => {
|
||||
fetchExportData({
|
||||
...pageParams,
|
||||
granularity: nextChartFilters.granularity,
|
||||
group_by: ['date', 'user', 'model', 'api_key'],
|
||||
filters: nextFilters,
|
||||
scope: initialScope,
|
||||
start_date: nextCommonFilters.start_date,
|
||||
end_date: nextCommonFilters.end_date
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const exportTableColumns: TableColumnType<any>[] = [
|
||||
{
|
||||
title: intl.formatMessage({ id: 'resources.table.index' }),
|
||||
width: 80,
|
||||
@@ -40,34 +92,124 @@ const ExportData: React.FC<{
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: 'dashboard.usage.export.date' }),
|
||||
dataIndex: 'date'
|
||||
dataIndex: ['date', 'label'],
|
||||
render: (text: string) => {
|
||||
return (
|
||||
<AutoTooltip ghost>
|
||||
<span className="text-primary">{text}</span>
|
||||
</AutoTooltip>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: 'dashboard.usage.export.user' }),
|
||||
dataIndex: 'user_name',
|
||||
title: 'Cluster',
|
||||
dataIndex: ['model', 'identity', 'value', 'cluster_name'],
|
||||
render: (text: string) => {
|
||||
return <AutoTooltip ghost>{text}</AutoTooltip>;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: 'dashboard.usage.export.model' }),
|
||||
dataIndex: 'model_id',
|
||||
dataIndex: ['model', 'identity', 'value', 'model_name'],
|
||||
render: (text: string, record: any) => {
|
||||
return (
|
||||
<AutoTooltip ghost>
|
||||
{record?.model?.identity?.value?.provider_name
|
||||
? `${record?.model?.identity?.value?.provider_name}/${text}`
|
||||
: text}
|
||||
</AutoTooltip>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: 'dashboard.usage.export.user' }),
|
||||
dataIndex: ['user', 'label'],
|
||||
render: (text: string) => {
|
||||
return <AutoTooltip ghost>{text}</AutoTooltip>;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'API Key',
|
||||
dataIndex: ['api_key', 'label'],
|
||||
render: (text: string, record: any) => {
|
||||
return <AutoTooltip ghost>{text}</AutoTooltip>;
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
title: 'API Key',
|
||||
dataIndex: 'api_key',
|
||||
render: (text: string, record: any) => {
|
||||
return <AutoTooltip ghost>{text}</AutoTooltip>;
|
||||
}
|
||||
title: 'Input Tokens',
|
||||
dataIndex: 'input_tokens'
|
||||
},
|
||||
{
|
||||
title: 'Output Tokens',
|
||||
dataIndex: 'output_tokens'
|
||||
},
|
||||
{
|
||||
title: 'Total Tokens',
|
||||
dataIndex: 'total_tokens'
|
||||
},
|
||||
{
|
||||
title: 'API Requests',
|
||||
dataIndex: 'api_requests'
|
||||
}
|
||||
];
|
||||
|
||||
const handleSubmit = () => {
|
||||
filterBar.onExportChart();
|
||||
exportJsonToExcel({
|
||||
fileName: `usage_export_${commonFilters.start_date}_${commonFilters.end_date}.xlsx`,
|
||||
sheets: [
|
||||
{
|
||||
jsonData: (dataSource.dataList || []).map((item: any) => ({
|
||||
date: item?.date?.label,
|
||||
user: item?.user?.label,
|
||||
cluster: item?.model?.identity?.value?.cluster_name,
|
||||
model: item?.model?.identity?.value?.model_name,
|
||||
api_key: item?.api_key?.label,
|
||||
input_tokens: item?.input_tokens,
|
||||
output_tokens: item?.output_tokens,
|
||||
total_tokens: item?.total_tokens,
|
||||
api_requests: item?.api_requests
|
||||
})),
|
||||
sheetName: 'usage',
|
||||
fields: [
|
||||
'date',
|
||||
'user',
|
||||
'model',
|
||||
'api_key',
|
||||
'input_tokens',
|
||||
'output_tokens',
|
||||
'total_tokens',
|
||||
'api_requests'
|
||||
],
|
||||
fieldLabels: {
|
||||
date: intl.formatMessage({ id: 'dashboard.usage.export.date' }),
|
||||
user: intl.formatMessage({ id: 'dashboard.usage.export.user' }),
|
||||
cluster: 'Cluster',
|
||||
model: intl.formatMessage({ id: 'dashboard.usage.export.model' }),
|
||||
api_key: 'API Key',
|
||||
input_tokens: 'Input Tokens',
|
||||
output_tokens: 'Output Tokens',
|
||||
total_tokens: 'Total Tokens',
|
||||
api_requests: 'API Requests'
|
||||
},
|
||||
formatMap: {}
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
const handlePageChange = (page: number, pageSize: number) => {
|
||||
setPageParams({ page, perPage: pageSize });
|
||||
fetchExportData({
|
||||
...pageParams,
|
||||
page,
|
||||
perPage: pageSize,
|
||||
granularity,
|
||||
group_by: ['date', 'user', 'model', 'api_key'],
|
||||
filters,
|
||||
scope: initialScope,
|
||||
start_date: commonFilters.start_date,
|
||||
end_date: commonFilters.end_date
|
||||
});
|
||||
};
|
||||
|
||||
const handleOnCancel = () => {
|
||||
@@ -76,11 +218,22 @@ const ExportData: React.FC<{
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
fetchData(commonFilters, {});
|
||||
fetchExportData({
|
||||
...pageParams,
|
||||
granularity,
|
||||
group_by: ['date', 'user', 'model', 'api_key'],
|
||||
filters,
|
||||
scope: initialScope,
|
||||
start_date: commonFilters.start_date,
|
||||
end_date: commonFilters.end_date
|
||||
});
|
||||
} else {
|
||||
cancelRequest();
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
console.log('export dataSource', filterBar);
|
||||
|
||||
return (
|
||||
<ScrollerModal
|
||||
title={intl.formatMessage({ id: 'dashboard.usage.export' })}
|
||||
@@ -105,17 +258,32 @@ const ExportData: React.FC<{
|
||||
></ModalFooter>
|
||||
}
|
||||
>
|
||||
<FilterBar {...filterBar} pageType="modal"></FilterBar>
|
||||
<FilterBar
|
||||
{...filterBar}
|
||||
pageType="modal"
|
||||
handlePickerChange={handlePickerChange}
|
||||
></FilterBar>
|
||||
<Table
|
||||
columns={exportTableColumns}
|
||||
tableLayout={'auto'}
|
||||
style={{ width: '100%', marginTop: '16px', minHeight: 300 }}
|
||||
dataSource={timeSeriesData.series || []}
|
||||
loading={loading}
|
||||
rowKey="id"
|
||||
dataSource={dataSource.dataList || []}
|
||||
rowKey={getBreakdownRowKey}
|
||||
loading={{
|
||||
spinning: loading,
|
||||
size: 'middle'
|
||||
}}
|
||||
virtual
|
||||
scroll={{ y: 400 }}
|
||||
pagination={false}
|
||||
pagination={{
|
||||
size: 'small',
|
||||
pageSize: pageParams.perPage,
|
||||
current: pageParams.page,
|
||||
total: dataSource.total || 0,
|
||||
onChange: handlePageChange,
|
||||
hideOnSinglePage: pageParams.perPage === 100,
|
||||
showSizeChanger: true
|
||||
}}
|
||||
></Table>
|
||||
</ScrollerModal>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import AutoTooltip from '@/components/auto-tooltip';
|
||||
import IconFont from '@/components/icon-font';
|
||||
import SealCascader from '@/components/seal-form/seal-cascader';
|
||||
import SimpleSelect from '@/components/seal-form/simple-select';
|
||||
import useRangePickerPreset from '@/pages/dashboard/hooks/use-rangepicker-preset';
|
||||
@@ -21,6 +22,9 @@ const DefaultDateConfig = {
|
||||
type OptionType = UsageFilterItem & {
|
||||
value: string;
|
||||
};
|
||||
|
||||
type DateType = 'date' | 'week' | 'month' | 'quarter' | 'year';
|
||||
|
||||
interface FilterBarProps {
|
||||
pageType?: 'page' | 'modal';
|
||||
scope: string;
|
||||
@@ -32,6 +36,7 @@ interface FilterBarProps {
|
||||
modelOptions: GroupOption<UsageFilterItem>[];
|
||||
userOptions: OptionType[];
|
||||
apiKeyOptions: GroupOption<UsageFilterItem>[];
|
||||
handlePickerChange: (picker: DateType) => void;
|
||||
onScopeChange: (value: string) => void;
|
||||
onDateChange: (dates: any, dateStrings: [string, string]) => void;
|
||||
onModelsChange: (value: string[]) => void;
|
||||
@@ -53,6 +58,7 @@ const FilterBar: React.FC<FilterBarProps> = (props) => {
|
||||
modelOptions,
|
||||
userOptions,
|
||||
apiKeyOptions,
|
||||
handlePickerChange,
|
||||
onDateChange,
|
||||
onModelsChange,
|
||||
onUsersChange,
|
||||
@@ -107,12 +113,22 @@ const FilterBar: React.FC<FilterBarProps> = (props) => {
|
||||
const exportMenuItems: MenuProps['items'] = [
|
||||
{
|
||||
key: 'chart',
|
||||
label: 'Export Chart Data',
|
||||
label: (
|
||||
<span className="flex-center gap-8">
|
||||
<IconFont type="icon-chart-01" style={{ fontSize: 14 }} />
|
||||
<span>Export Chart Data</span>
|
||||
</span>
|
||||
),
|
||||
onClick: onExportChart
|
||||
},
|
||||
{
|
||||
key: 'table',
|
||||
label: 'Export Table Data',
|
||||
label: (
|
||||
<span className="flex-center gap-8">
|
||||
<IconFont type="icon-table" style={{ fontSize: 14 }} />
|
||||
<span>Export Table Data</span>
|
||||
</span>
|
||||
),
|
||||
onClick: onExportTable
|
||||
}
|
||||
];
|
||||
@@ -187,6 +203,11 @@ const FilterBar: React.FC<FilterBarProps> = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
const onPickerChange = (picker: DateType) => {
|
||||
handleOnPickerChange(picker);
|
||||
handlePickerChange(picker);
|
||||
};
|
||||
|
||||
const renderFooter = () => {
|
||||
return (
|
||||
<Segmented
|
||||
@@ -208,19 +229,19 @@ const FilterBar: React.FC<FilterBarProps> = (props) => {
|
||||
flex: 1
|
||||
}
|
||||
}}
|
||||
onChange={handleOnPickerChange}
|
||||
onChange={onPickerChange}
|
||||
options={[
|
||||
{
|
||||
label: 'Day',
|
||||
value: 'date'
|
||||
},
|
||||
{
|
||||
label: 'Week',
|
||||
value: 'week'
|
||||
},
|
||||
{
|
||||
label: 'Month',
|
||||
value: 'month'
|
||||
},
|
||||
{
|
||||
label: 'Week',
|
||||
value: 'week'
|
||||
}
|
||||
]}
|
||||
></Segmented>
|
||||
@@ -232,11 +253,18 @@ const FilterBar: React.FC<FilterBarProps> = (props) => {
|
||||
return (
|
||||
<span className="flex-center gap-8">
|
||||
<span>{data.label}</span>
|
||||
{data.isCurrent && <span className="text-tertiary"> [Current]</span>}
|
||||
{data.isCurrent && (
|
||||
<span className="text-tertiary"> [Current Account]</span>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
// only for dates greater than the current day should be disabled.
|
||||
const disabledDate = (current: dayjs.Dayjs) => {
|
||||
return current && current > dayjs().endOf('day');
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={FilterBarCss.wrapper}>
|
||||
<div className={FilterBarCss.filters}>
|
||||
@@ -248,12 +276,11 @@ const FilterBar: React.FC<FilterBarProps> = (props) => {
|
||||
]}
|
||||
format={'YYYY-MM-DD'}
|
||||
picker={picker}
|
||||
disabledDate={disabledRangeDaysDate}
|
||||
disabledDate={disabledDate}
|
||||
presets={rangePresets}
|
||||
allowClear={false}
|
||||
style={{ width: 240 }}
|
||||
onChange={onDateChange}
|
||||
renderExtraFooter={renderFooter}
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
@@ -285,9 +312,7 @@ const FilterBar: React.FC<FilterBarProps> = (props) => {
|
||||
}}
|
||||
maxTagCount={1}
|
||||
size="small"
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'dashboard.usage.selectmodel'
|
||||
})}
|
||||
placeholder={'Filter by model'}
|
||||
options={modelOptions}
|
||||
showCheckedStrategy="SHOW_CHILD"
|
||||
displayRender={displayRender}
|
||||
@@ -304,7 +329,7 @@ const FilterBar: React.FC<FilterBarProps> = (props) => {
|
||||
showSearch
|
||||
mode="multiple"
|
||||
options={userOptions}
|
||||
placeholder="User"
|
||||
placeholder="Filter by user"
|
||||
styles={{
|
||||
wrapper: { flex: 1, maxWidth: 240, minWidth: 150 }
|
||||
}}
|
||||
@@ -342,7 +367,7 @@ const FilterBar: React.FC<FilterBarProps> = (props) => {
|
||||
}}
|
||||
maxTagCount={1}
|
||||
size="small"
|
||||
placeholder="API Key"
|
||||
placeholder="Filter by API key"
|
||||
options={apiKeyOptions}
|
||||
showCheckedStrategy="SHOW_CHILD"
|
||||
value={activeApiKeys}
|
||||
@@ -359,7 +384,7 @@ const FilterBar: React.FC<FilterBarProps> = (props) => {
|
||||
mode="multiple"
|
||||
options={apiKeyOptions?.[0]?.children || []}
|
||||
maxTagCount={0}
|
||||
placeholder="API Key"
|
||||
placeholder="Filter by API key"
|
||||
styles={{
|
||||
wrapper: { flex: 1, maxWidth: 240, minWidth: 100 }
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user