fix: usage ux
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
import CardWrapper from '@/components/card-wrapper';
|
||||
import { SimpleCard } from '@/components/card-wrapper/simple-card';
|
||||
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 { Divider, Segmented } from 'antd';
|
||||
import { Segmented } from 'antd';
|
||||
import dayjs from 'dayjs';
|
||||
import React, { useMemo } from 'react';
|
||||
import styled from 'styled-components';
|
||||
@@ -151,7 +150,7 @@ const DailyUsage: React.FC<DailyUsageProps> = (props) => {
|
||||
<ControlsWrapper>
|
||||
<div className="group">
|
||||
<BaseSelect
|
||||
variant="outlined"
|
||||
variant="borderless"
|
||||
prefix={<ControlLabel>Metric</ControlLabel>}
|
||||
options={metricOptions}
|
||||
value={metric}
|
||||
@@ -160,7 +159,7 @@ const DailyUsage: React.FC<DailyUsageProps> = (props) => {
|
||||
/>
|
||||
|
||||
<BaseSelect
|
||||
variant="outlined"
|
||||
variant="borderless"
|
||||
prefix={<ControlLabel>Group by</ControlLabel>}
|
||||
options={groupByOptions}
|
||||
value={groupBy}
|
||||
@@ -176,9 +175,9 @@ const DailyUsage: React.FC<DailyUsageProps> = (props) => {
|
||||
onChange={onGranularityChange}
|
||||
></Segmented>
|
||||
</ControlsWrapper>
|
||||
<Divider style={{ margin: 0 }} />
|
||||
{/* <Divider style={{ margin: 0 }} /> */}
|
||||
|
||||
<SimpleCard dataList={summaryCards} height={80} />
|
||||
{/* <SimpleCard dataList={summaryCards} height={80} /> */}
|
||||
<MixLineBar
|
||||
chartData={chartData}
|
||||
seriesData={[]}
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
import AutoTooltip from '@/components/auto-tooltip';
|
||||
import ModalFooter from '@/components/modal-footer';
|
||||
import ScrollerModal from '@/components/scroller-modal';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Table, TableColumnType } from 'antd';
|
||||
import React, { useEffect } from 'react';
|
||||
import { useUsageFilters } from '../hooks/use-usage-filters';
|
||||
import FilterBar from './filter-bar';
|
||||
|
||||
const ExportData: React.FC<{
|
||||
open: boolean;
|
||||
onCancel: () => void;
|
||||
initialScope: string;
|
||||
metaData: any;
|
||||
}> = (props) => {
|
||||
const { open, onCancel, initialScope, metaData } = props || {};
|
||||
const intl = useIntl();
|
||||
|
||||
const {
|
||||
filters,
|
||||
commonFilters,
|
||||
fetchData,
|
||||
loading,
|
||||
timeSeriesData,
|
||||
filterBar
|
||||
} = useUsageFilters({
|
||||
initialScope: initialScope,
|
||||
metaData,
|
||||
chartFilters: {},
|
||||
summaryColumns: {}
|
||||
});
|
||||
|
||||
const exportTableColumns: TableColumnType[] = [
|
||||
{
|
||||
title: intl.formatMessage({ id: 'resources.table.index' }),
|
||||
width: 80,
|
||||
render(text: any, row: any, index: number) {
|
||||
return index + 1;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: 'dashboard.usage.export.date' }),
|
||||
dataIndex: 'date'
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: 'dashboard.usage.export.user' }),
|
||||
dataIndex: 'user_name',
|
||||
render: (text: string) => {
|
||||
return <AutoTooltip ghost>{text}</AutoTooltip>;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: 'dashboard.usage.export.model' }),
|
||||
dataIndex: 'model_id',
|
||||
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>;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const handleSubmit = () => {
|
||||
filterBar.onExportChart();
|
||||
};
|
||||
|
||||
const handleOnCancel = () => {
|
||||
onCancel?.();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
fetchData(commonFilters, {});
|
||||
} else {
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
return (
|
||||
<ScrollerModal
|
||||
title={intl.formatMessage({ id: 'dashboard.usage.export' })}
|
||||
open={open}
|
||||
centered={false}
|
||||
onCancel={handleOnCancel}
|
||||
destroyOnHidden={true}
|
||||
closeIcon={true}
|
||||
mask={{
|
||||
closable: false
|
||||
}}
|
||||
keyboard={false}
|
||||
width={1200}
|
||||
style={{
|
||||
top: '10%'
|
||||
}}
|
||||
footer={
|
||||
<ModalFooter
|
||||
onOk={handleSubmit}
|
||||
onCancel={handleOnCancel}
|
||||
okText={intl.formatMessage({ id: 'common.button.export' })}
|
||||
></ModalFooter>
|
||||
}
|
||||
>
|
||||
<FilterBar {...filterBar} pageType="modal"></FilterBar>
|
||||
<Table
|
||||
columns={exportTableColumns}
|
||||
tableLayout={'auto'}
|
||||
style={{ width: '100%', marginTop: '16px', minHeight: 300 }}
|
||||
dataSource={timeSeriesData.series || []}
|
||||
loading={loading}
|
||||
rowKey="id"
|
||||
virtual
|
||||
scroll={{ y: 400 }}
|
||||
pagination={false}
|
||||
></Table>
|
||||
</ScrollerModal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExportData;
|
||||
@@ -6,7 +6,7 @@ import ProviderLogo from '@/pages/maas-provider/components/provider-logo';
|
||||
import { useModel } from '@@/plugin-model';
|
||||
import { DownloadOutlined, SyncOutlined } from '@ant-design/icons';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Button, DatePicker, Dropdown, MenuProps } from 'antd';
|
||||
import { Button, DatePicker, Dropdown, MenuProps, Segmented } from 'antd';
|
||||
import dayjs from 'dayjs';
|
||||
import React from 'react';
|
||||
import { GroupOption } from '../config';
|
||||
@@ -22,6 +22,7 @@ type OptionType = UsageFilterItem & {
|
||||
value: string;
|
||||
};
|
||||
interface FilterBarProps {
|
||||
pageType?: 'page' | 'modal';
|
||||
scope: string;
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
@@ -38,22 +39,20 @@ interface FilterBarProps {
|
||||
onApiKeysChange: (value: string[]) => void;
|
||||
onExport?: () => void;
|
||||
handleSearch?: () => void;
|
||||
onExportChart: () => void;
|
||||
onExportTable: () => void;
|
||||
onExportChart?: () => void;
|
||||
onExportTable?: () => void;
|
||||
}
|
||||
|
||||
const FilterBar: React.FC<FilterBarProps> = (props) => {
|
||||
const {
|
||||
scope,
|
||||
pageType = 'page',
|
||||
startDate,
|
||||
endDate,
|
||||
selectedModels,
|
||||
selectedUsers,
|
||||
selectedApiKeys,
|
||||
modelOptions,
|
||||
userOptions,
|
||||
apiKeyOptions,
|
||||
onScopeChange,
|
||||
onDateChange,
|
||||
onModelsChange,
|
||||
onUsersChange,
|
||||
@@ -63,41 +62,40 @@ const FilterBar: React.FC<FilterBarProps> = (props) => {
|
||||
handleSearch
|
||||
} = props;
|
||||
const intl = useIntl();
|
||||
const { disabledRangeDaysDate, rangePresets } = useRangePickerPreset({
|
||||
range: DefaultDateConfig.maxRange,
|
||||
disabledDate: true,
|
||||
presetRanges: [
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'dashboard.usage.datePicker.last7days'
|
||||
}),
|
||||
value: [dayjs().add(-6, 'd'), dayjs()]
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'dashboard.usage.datePicker.last30days'
|
||||
}),
|
||||
value: [dayjs().add(-29, 'd'), dayjs()]
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'dashboard.usage.datePicker.last60days'
|
||||
}),
|
||||
value: [dayjs().add(-59, 'd'), dayjs()]
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'dashboard.usage.datePicker.last90days'
|
||||
}),
|
||||
value: [dayjs().add(-89, 'd'), dayjs()]
|
||||
}
|
||||
]
|
||||
});
|
||||
const { disabledRangeDaysDate, rangePresets, picker, handleOnPickerChange } =
|
||||
useRangePickerPreset({
|
||||
range: DefaultDateConfig.maxRange,
|
||||
disabledDate: true,
|
||||
presetRanges: [
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'dashboard.usage.datePicker.last7days'
|
||||
}),
|
||||
value: [dayjs().add(-6, 'd'), dayjs()]
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'dashboard.usage.datePicker.last30days'
|
||||
}),
|
||||
value: [dayjs().add(-29, 'd'), dayjs()]
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'dashboard.usage.datePicker.last60days'
|
||||
}),
|
||||
value: [dayjs().add(-59, 'd'), dayjs()]
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: 'dashboard.usage.datePicker.last90days'
|
||||
}),
|
||||
value: [dayjs().add(-89, 'd'), dayjs()]
|
||||
}
|
||||
]
|
||||
});
|
||||
const [activeModels, setActiveModels] = React.useState<valueType[][]>([]);
|
||||
const [activeApiKeys, setActiveApiKeys] = React.useState<valueType[][]>([]);
|
||||
const [activeUserApiKeys, setActiveUserApiKeys] = React.useState<valueType[]>(
|
||||
[]
|
||||
);
|
||||
|
||||
const initialInfo = useModel('@@initialState');
|
||||
const { initialState } = initialInfo || {};
|
||||
|
||||
@@ -184,6 +182,46 @@ const FilterBar: React.FC<FilterBarProps> = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
const renderFooter = () => {
|
||||
return (
|
||||
<Segmented
|
||||
size="middle"
|
||||
shape="round"
|
||||
value={picker}
|
||||
styles={{
|
||||
root: {
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
marginBlock: 8
|
||||
},
|
||||
item: {
|
||||
flex: 1
|
||||
},
|
||||
label: {
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
flex: 1
|
||||
}
|
||||
}}
|
||||
onChange={handleOnPickerChange}
|
||||
options={[
|
||||
{
|
||||
label: 'Day',
|
||||
value: 'date'
|
||||
},
|
||||
{
|
||||
label: 'Week',
|
||||
value: 'week'
|
||||
},
|
||||
{
|
||||
label: 'Month',
|
||||
value: 'month'
|
||||
}
|
||||
]}
|
||||
></Segmented>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={FilterBarCss.wrapper}>
|
||||
<div className={FilterBarCss.filters}>
|
||||
@@ -193,12 +231,14 @@ const FilterBar: React.FC<FilterBarProps> = (props) => {
|
||||
dayjs().add(-DefaultDateConfig.defaultRange, 'd'),
|
||||
dayjs()
|
||||
]}
|
||||
picker={picker}
|
||||
disabledDate={disabledRangeDaysDate}
|
||||
presets={rangePresets}
|
||||
allowClear={false}
|
||||
style={{ width: 240 }}
|
||||
value={[dayjs(startDate), dayjs(endDate)]}
|
||||
onChange={onDateChange}
|
||||
renderExtraFooter={renderFooter}
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
@@ -318,9 +358,11 @@ const FilterBar: React.FC<FilterBarProps> = (props) => {
|
||||
icon={<SyncOutlined></SyncOutlined>}
|
||||
></Button>
|
||||
</div>
|
||||
<Dropdown menu={{ items: exportMenuItems }}>
|
||||
<Button icon={<DownloadOutlined />} />
|
||||
</Dropdown>
|
||||
{pageType === 'page' && (
|
||||
<Dropdown menu={{ items: exportMenuItems }}>
|
||||
<Button icon={<DownloadOutlined />} />
|
||||
</Dropdown>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user