fix: ui issues

This commit is contained in:
jialin
2024-07-03 15:27:35 +08:00
parent 316019586f
commit 81e9a3cc92
46 changed files with 1075 additions and 305 deletions
+9 -10
View File
@@ -240,7 +240,7 @@ const Models: React.FC = () => {
}}
>
<Column
title={intl.formatMessage({ id: 'apikeys.table.name' })}
title={intl.formatMessage({ id: 'common.table.name' })}
dataIndex="name"
key="name"
width={400}
@@ -249,6 +249,14 @@ const Models: React.FC = () => {
}}
/>
<Column
title={intl.formatMessage({ id: 'apikeys.form.expiretime' })}
dataIndex="expires_at"
key="expiration"
render={(text, record) => {
return dayjs(text).format('YYYY-MM-DD HH:mm:ss');
}}
/>
<Column
title={intl.formatMessage({ id: 'common.table.createTime' })}
dataIndex="created_at"
@@ -261,14 +269,6 @@ const Models: React.FC = () => {
return dayjs(text).format('YYYY-MM-DD HH:mm:ss');
}}
/>
<Column
title={intl.formatMessage({ id: 'apikeys.form.expiretime' })}
dataIndex="expires_at"
key="expiration"
render={(text, record) => {
return dayjs(text).format('YYYY-MM-DD HH:mm:ss');
}}
/>
<Column
title={intl.formatMessage({ id: 'common.table.operation' })}
key="operation"
@@ -281,7 +281,6 @@ const Models: React.FC = () => {
<Button
onClick={() => handleDelete(record)}
size="small"
type="primary"
danger
icon={<DeleteOutlined></DeleteOutlined>}
></Button>
@@ -72,7 +72,7 @@ const ActiveTable = () => {
const data = useContext(DashboardContext).active_models || [];
const modelColumns = [
{
title: intl.formatMessage({ id: 'dashboard.activeModels.name' }),
title: intl.formatMessage({ id: 'common.table.name' }),
dataIndex: 'name',
key: 'name'
},
@@ -86,9 +86,16 @@ const ActiveTable = () => {
// },
{
title: intl.formatMessage({ id: 'dashboard.allocatevram' }),
dataIndex: 'allocate_gpu_memory_utilization',
key: 'gpu_memory_utilization',
render: (text: any, record: any) => <span>{convertFileSize(text)}</span>
dataIndex: 'resource_claim.memory',
key: 'gpu_memory',
render: (text: any, record: any) => {
return (
<span>
{convertFileSize(record.resource_claim?.gpu_memory || 0)} /{' '}
{convertFileSize(record.resource_claim?.memory || 0)}
</span>
);
}
},
{
title: intl.formatMessage({ id: 'dashboard.runninginstances' }),
@@ -1,11 +1,12 @@
:local(.card-body) {
box-shadow: none !important;
:global(.ant-card-body) {
height: 110px;
display: flex;
justify-content: space-around;
// box-shadow: var(--box-shadow-base);
border-radius: var(--ant-border-radius-lg);
// border: 1px solid var(--ant-color-border);
border: 1px solid var(--color-border-1);
}
}
+1 -1
View File
@@ -15,7 +15,7 @@ const renderCardItem = (data: {
const { label, value, bgColor } = data;
return (
<Card
bordered={true}
bordered={false}
style={{ background: bgColor }}
className={styles['card-body']}
>
@@ -1,89 +1,174 @@
import LineChart from '@/components/charts/line-chart';
import Chart from '@/components/echarts/chart';
import { getLocale, useIntl } from '@umijs/max';
import dayjs from 'dayjs';
import _ from 'lodash';
import { useCallback, useContext, useEffect, useState } from 'react';
import { DashboardContext } from '../config/dashboard-context';
const chartColorMap = {
tickLineColor: 'rgba(217,217,217,0.5)',
axislabelColor: 'rgba(0, 0, 0, 0.4)'
};
const TypeKeyMap = {
cpu: {
label: 'CPU',
type: 'CPU',
intl: false,
color:
'linear-gradient(90deg,rgba(84, 204, 152,0.8) 0%,rgba(0, 168, 143,.7) 100%)'
color: 'rgba(250, 173, 20,.8)'
},
memory: {
label: 'dashboard.memory',
type: 'Memory',
intl: true,
color:
'linear-gradient(90deg,rgba(249, 248, 113,.8) 0%,rgba(255, 199, 92,0.7) 100%)'
color: 'rgba(114, 46, 209,.8)'
},
gpu: {
label: 'GPU',
type: 'GPU',
intl: false,
color: 'rgba(84, 204, 152,0.8)'
color: 'rgba(84, 204, 152,.8)'
},
gpu_memory: {
label: 'dashboard.vram',
type: 'VRAM',
intl: true,
color:
'linear-gradient(90deg,rgba(84, 204, 152,0.8) 0%,rgba(0, 168, 143,.7) 100%)'
color: 'rgba(255, 107, 179, 80%)'
}
};
const option = {
title: {
text: ''
},
legend: {
itemWidth: 8,
itemHeight: 8,
data: []
},
grid: {
left: 0,
right: 20,
bottom: 20,
containLabel: true
},
tooltip: {
trigger: 'axis',
formatter(params: any) {
let result = `<span class="tooltip-x-name">${params[0].axisValue}</span>`;
params.forEach((item: any) => {
result += `<span class="tooltip-item">
<span class="tooltip-item-name">
<span style="display:inline-block;margin-right:5px;border-radius:8px;width:8px;height:8px;background-color:${item.color};"></span>
<span class="tooltip-title">${item.seriesName}</span>:
</span>
<span class="tooltip-value">${item.data.value}</span>
</span>`;
});
return `<div class="tooltip-wrapper">${result}</div>`;
}
},
xAxis: {
type: 'category',
boundaryGap: true,
axisTick: {
show: true,
lineStyle: {
color: chartColorMap.tickLineColor
}
},
axisLabel: {
color: chartColorMap.axislabelColor,
// fontFamily: 'unset',
fontSize: 12
},
axisLine: {
show: false
},
data: []
},
yAxis: {
max: 100,
min: 0,
splitLine: {
show: true,
lineStyle: {
type: 'dashed'
}
},
axisLabel: {
color: chartColorMap.axislabelColor,
// fontFamily: 'unset',
fontSize: 12
},
axisTick: {
show: false
},
type: 'value'
},
series: []
};
const UtilizationOvertime: React.FC = () => {
const intl = useIntl();
const locale = getLocale();
const [dataOptions, setDataOptions] = useState<any>(option);
const data = useContext(DashboardContext)?.system_load?.history || {};
const [result, setResult] = useState<
{ time: string; value: number; type: string }[]
>([]);
const typeList = ['gpu', 'cpu', 'memory', 'gpu_memory'];
const sliderConfig = {
y: false,
x: {
style: {
selectionFill: 'rgb(84, 204, 152)',
selectionFillOpacity: 0.1,
handleIconFill: 'rgb(84, 204, 152)',
handleIconFillOpacity: 0.15,
handleIconStrokeOpacity: 0,
sparklineType: 'line',
sparkline: true
},
sparkline: true
}
};
const labelFormatter = (value: any) => {
return `${value}%`;
};
const generateData = useCallback(() => {
const list: { value: number; time: string; type: string }[] = [];
_.each(typeList, (type: any) => {
const dataList = _.map(_.get(data, type, []), (item: any) => {
const value = _.round(_.get(item, 'value', 0), 1);
const time = dayjs(item.timestamp * 1000).format('HH:mm:ss');
const itemtype = _.get(TypeKeyMap, [type, 'intl'], false)
? intl.formatMessage({
id: _.get(TypeKeyMap, [type, 'label'], '')
})
: _.get(TypeKeyMap, [type, 'label'], '');
return {
value,
time,
type: itemtype,
color: 'red'
};
});
list.push(...dataList);
const legendData: string[] = [];
const xAxisData: string[] = [];
let list: { value: number; time: string; type: string }[] = [];
list = _.map(typeList, (item: string) => {
const itemConfig = _.get(TypeKeyMap, item, {});
console.log('itemConfig', itemConfig);
const name = itemConfig.intl
? intl.formatMessage({ id: itemConfig.label })
: itemConfig.label;
legendData.push(name);
const itemDataList = _.get(data, item, []);
return {
type: 'line',
smooth: true,
showSymbol: false,
itemStyle: {
color: itemConfig.color
},
lineStyle: {
width: 1.5,
opacity: 0.7,
color: itemConfig.color
},
name: name,
data: _.map(itemDataList, (item: any) => {
xAxisData.push(dayjs(item.timestamp * 1000).format('HH:mm:ss'));
return {
time: dayjs(item.timestamp * 1000).format('HH:mm:ss'),
value: _.round(_.get(item, 'value', 0), 1)
};
})
};
});
setDataOptions({
...option,
legend: {
...option.legend,
data: legendData
},
xAxis: {
...option.xAxis,
data: _.uniq(xAxisData)
},
series: list
});
setResult(list);
}, [data, locale]);
useEffect(() => {
@@ -92,13 +177,7 @@ const UtilizationOvertime: React.FC = () => {
return (
<>
<LineChart
data={result}
locale={locale}
height={390}
labelFormatter={labelFormatter}
slider={sliderConfig}
/>
<Chart height={390} options={dataOptions} width="100%"></Chart>
</>
);
};
+102 -84
View File
@@ -1,7 +1,7 @@
import CardWrapper from '@/components/card-wrapper';
import AreaChart from '@/components/charts/area';
import ColumnBar from '@/components/charts/column-bar';
import HBar from '@/components/charts/h-bar';
import BarChart from '@/components/echarts/bar-chart';
import HBar from '@/components/echarts/h-bar';
import LineChart from '@/components/echarts/line-chart';
import PageTools from '@/components/page-tools';
import breakpoints from '@/config/breakpoints';
import useWindowResize from '@/hooks/use-window-resize';
@@ -13,7 +13,14 @@ import _ from 'lodash';
import { useContext, useEffect, useState } from 'react';
import { DashboardContext } from '../config/dashboard-context';
const { RangePicker } = DatePicker;
const baseColorMap = {
baseL2: 'rgba(13,171,219,0.8)',
baseL1: 'rgba(0,34,255,0.8)',
base: 'rgba(0,123,255,0.8)',
baseR1: 'rgba(0,255,233,0.8)',
baseR2: 'rgba(48,0,255,0.8)',
baseR3: 'rgba(85,167,255,0.8)'
};
const times = [
'june 1',
'june 2',
@@ -94,15 +101,15 @@ const tokenUsage = TokensData.map((val, i) => {
const getCurrentMonthDays = () => {
const now = dayjs();
const firstDayOfMonth = now.startOf('month');
const dateRange = [];
let currentDate = firstDayOfMonth;
const daysInMonth = now.daysInMonth();
const year = dayjs().year();
const month = dayjs().month() + 1;
while (currentDate.isBefore(now) || currentDate.isSame(now, 'day')) {
dateRange.push(currentDate.format('YYYY-MM-DD'));
currentDate = currentDate.add(1, 'day');
const dates = [];
for (let day = 1; day <= daysInMonth; day++) {
dates.push(dayjs(`${year}-${month}-${day}`).format('YYYY-MM-DD'));
}
return dateRange;
return dates;
};
const Usage = () => {
@@ -110,42 +117,64 @@ const Usage = () => {
const { size } = useWindowResize();
const [paddingRight, setPaddingRight] = useState<string>('20px');
const [requestData, setRequestData] = useState<
{ time: string; value: number }[]
{
name: string;
color: string;
areaStyle: any;
data: { time: string; value: number }[];
}[]
>([]);
const currentMonthDays = getCurrentMonthDays();
const [tokenData, setTokenData] = useState<{ time: string; value: number }[]>(
[]
);
const [userData, setUserData] = useState<{ name: string; value: number }[]>(
[]
);
const [dateRange, setDateRange] = useState<string[]>(getCurrentMonthDays());
const [xAxisData, setXAxisData] = useState<string[]>(currentMonthDays);
const [dateRange, setDateRange] = useState<string[]>(currentMonthDays);
const [topUserList, setTopUseList] = useState<string[]>([]);
const data = useContext(DashboardContext)?.model_usage || {};
console.log('dateRange', dateRange);
const handleSelectDate = (dateString: string) => {};
const generateData = () => {
const requestList: { time: string; value: number }[] = [];
const tokenList: {
time: string;
value: number;
const requestList: {
name: string;
color: string;
}[] = [];
const userList: {
name: string;
value: number;
type: string;
color: string;
}[] = [];
areaStyle: any;
data: { time: string; value: number }[];
} = {
name: 'API Request',
areaStyle: {},
color: baseColorMap.base,
data: []
};
_.each(data.api_request_history, (item: any) => {
requestList.push({
time: dayjs(item.timestamp * 1000).format('YYYY-MM-DD'),
value: item.value
});
});
const completionData: any = {
name: 'completion_token',
color: baseColorMap.base,
data: []
};
const prompData: any = {
name: 'prompt_token',
color: baseColorMap.baseR3,
data: []
};
const topUserPrompt: any = {
name: 'prompt_token',
color: baseColorMap.baseR3,
data: []
};
const topUserCompletion: any = {
name: 'completion_token',
color: baseColorMap.base,
data: []
};
const users: string[] = [];
_.each(dateRange, (date: string) => {
// tokens data
@@ -153,18 +182,14 @@ const Usage = () => {
return dayjs(item.timestamp * 1000).format('YYYY-MM-DD') === date;
});
if (!item) {
tokenList.push({
time: date,
name: 'completion_token',
color: 'rgba(84, 204, 152,0.8)',
completionData.data.push({
titme: date,
value: 0
});
} else {
tokenList.push({
time: dayjs(item.timestamp * 1000).format('YYYY-MM-DD'),
name: 'completion_token',
color: 'rgba(84, 204, 152,0.8)',
value: item.value
completionData.data.push({
value: item.value,
time: dayjs(item.timestamp * 1000).format('YYYY-MM-DD')
});
}
@@ -172,57 +197,58 @@ const Usage = () => {
return dayjs(item.timestamp * 1000).format('YYYY-MM-DD') === date;
});
if (!promptItem) {
tokenList.push({
time: date,
name: 'prompt_token',
color: 'rgba(0, 170, 173, 0.8)',
value: 0
prompData.data.push({
value: 0,
time: date
});
} else {
tokenList.push({
time: dayjs(promptItem.timestamp * 1000).format('YYYY-MM-DD'),
name: 'prompt_token',
color: 'rgba(0, 170, 173, 0.8)',
value: promptItem.value
prompData.data.push({
value: promptItem.value,
time: dayjs(promptItem.timestamp * 1000).format('YYYY-MM-DD')
});
}
// api request data
// ============== api request data =================
const requestItem = _.find(data.api_request_history, (item: any) => {
return dayjs(item.timestamp * 1000).format('YYYY-MM-DD') === date;
});
if (!requestItem) {
requestList.push({
requestList.data.push({
time: date,
value: 0
});
} else {
requestList.push({
requestList.data.push({
time: dayjs(requestItem.timestamp * 1000).format('YYYY-MM-DD'),
value: requestItem.value
});
}
});
// ========== top users ============
_.each(data.top_users, (item: any) => {
userList.push({
users.push(item.username);
topUserPrompt.data.push({
name: item.username,
type: 'completion_token',
color: 'rgba(84, 204, 152,0.8)',
value: item.completion_token_count
});
userList.push({
name: item.username,
type: 'prompt_token',
color: 'rgba(0, 170, 173, 0.8)',
value: item.prompt_token_count
});
topUserCompletion.data.push({
name: item.username,
value: item.completion_token_count
});
});
setRequestData(requestList);
setTokenData(tokenList);
setUserData(userList);
console.log('usage=============', {
requestList,
xAxisData
});
setRequestData([requestList]);
setUserData([topUserCompletion, topUserPrompt]);
setTopUseList(users);
setTokenData([completionData, prompData]);
};
const labelFormatter = (v: any) => {
@@ -270,28 +296,25 @@ const Usage = () => {
<CardWrapper style={{ width: '100%' }}>
<Row style={{ width: '100%' }}>
<Col span={12}>
<AreaChart
<LineChart
title={intl.formatMessage({ id: 'dashboard.apirequest' })}
data={requestData}
seriesData={requestData}
xAxisData={xAxisData}
xField="time"
yField="value"
height={360}
color={baseColorMap.baseR3}
labelFormatter={labelFormatter}
></AreaChart>
></LineChart>
</Col>
<Col span={12}>
<ColumnBar
<BarChart
title={intl.formatMessage({ id: 'dashboard.tokens' })}
data={tokenData}
group={false}
colorField="name"
stack={true}
xField="time"
legend={false}
yField="value"
seriesData={tokenData}
xAxisData={xAxisData}
height={360}
labelFormatter={labelFormatter}
></ColumnBar>
></BarChart>
</Col>
</Row>
</CardWrapper>
@@ -300,13 +323,8 @@ const Usage = () => {
<CardWrapper>
<HBar
title={intl.formatMessage({ id: 'dashboard.topusers' })}
data={userData}
stack={true}
legend={false}
showYAxis={false}
colorField="type"
xField="name"
yField="value"
seriesData={userData}
xAxisData={topUserList}
height={360}
></HBar>
</CardWrapper>
+1 -1
View File
@@ -100,7 +100,7 @@ const AddModal: React.FC<AddModalProps> = (props) => {
const handleOnSearchRepo = async (text: string) => {
try {
const params = {
q: `${text} gguf`,
q: `${text}`,
type: 'model'
};
const res = await callHuggingfaceQuickSearch(params);
+6 -5
View File
@@ -162,9 +162,6 @@ const Models: React.FC = () => {
_.each(list, (data: any) => {
updateChunkedList(data);
});
if (!dataSource.length) {
handleFilter();
}
};
const createModelsChunkRequest = () => {
@@ -367,7 +364,10 @@ const Models: React.FC = () => {
</Col>
<Col span={4}>
<span style={{ paddingLeft: '22px' }}>
<span
style={{ paddingLeft: '68px' }}
className="flex justify-center"
>
{item.state && (
<StatusTag
download={
@@ -478,7 +478,7 @@ const Models: React.FC = () => {
}}
>
<SealColumn
title={intl.formatMessage({ id: 'models.table.name' })}
title={intl.formatMessage({ id: 'common.table.name' })}
dataIndex="name"
key="name"
width={400}
@@ -494,6 +494,7 @@ const Models: React.FC = () => {
title={intl.formatMessage({ id: 'models.form.replicas' })}
dataIndex="replicas"
key="replicas"
align="center"
span={4}
/>
<SealColumn
@@ -39,13 +39,6 @@ const ChatFooter: React.FC<ChatFooterProps> = (props) => {
},
{ enabled: !disabled }
);
useHotkeys(
HotKeys.CREATE.join(','),
(e) => {
onNewMessage();
},
{ enabled: !disabled }
);
return (
<div className="chat-footer">
@@ -59,7 +52,6 @@ const ChatFooter: React.FC<ChatFooterProps> = (props) => {
onClick={onNewMessage}
>
{intl.formatMessage({ id: 'playground.newMessage' })}
<span className="m-l-5 opct-7">CTRL+SHIFT+ N</span>
</Button>
<Button
icon={<DeleteOutlined></DeleteOutlined>}
@@ -126,8 +126,13 @@ const MessageList: React.FC<MessageProps> = (props) => {
}
};
const handleClear = () => {
const headItem = _.get(messageList, '0');
setMessageList(headItem ? [headItem] : []);
setMessageList([
{
role: Roles.User,
content: '',
uid: messageId.current + 1
}
]);
};
const handleView = () => {
@@ -3,7 +3,7 @@ import SealInput from '@/components/seal-form/seal-input';
import SealSelect from '@/components/seal-form/seal-select';
import { INPUT_WIDTH } from '@/constants';
import { useIntl } from '@umijs/max';
import { Button, Form, InputNumber, Slider } from 'antd';
import { Form, InputNumber, Slider } from 'antd';
import _ from 'lodash';
import { useEffect, useState } from 'react';
import { queryModelsList } from '../apis';
@@ -149,9 +149,6 @@ const ParamsSettings: React.FC<ParamsSettingsProps> = ({
</Form.Item>
<h3 className="m-b-20 m-l-10 flex-between flex-center">
<span>{intl.formatMessage({ id: 'playground.parameters' })}</span>
<Button size="small" onClick={handleResetParams}>
{intl.formatMessage({ id: 'common.button.reset' })}
</Button>
</h3>
<Form.Item<ParamsSettingsFormProps>
name="temperature"
+84 -63
View File
@@ -1,4 +1,3 @@
import CardWrapper from '@/components/card-wrapper';
import FormButtons from '@/components/form-buttons';
import SealInput from '@/components/seal-form/seal-input';
import { PasswordReg } from '@/config';
@@ -18,11 +17,12 @@ const Profile: React.FC = () => {
const [form] = Form.useForm();
const intl = useIntl();
const newpasswordValue = Form.useWatch('new_password', form);
const handleOnFinish = async (values: any) => {
try {
await updatePassword(values);
await updatePassword({
new_password: values.new_password,
current_password: values.current_password
});
message.success(intl.formatMessage({ id: 'common.message.success' }));
} catch (error) {}
};
@@ -43,20 +43,14 @@ const Profile: React.FC = () => {
}}
extra={[]}
>
<CardWrapper
style={{
padding: 'var(--layout-content-inlinepadding)',
width: 'max-content'
}}
<Form
style={{ width: '524px' }}
name="profileForm"
form={form}
onFinish={handleOnFinish}
onFinishFailed={handleOnFinishFailed}
>
<Form
style={{ width: '524px' }}
name="profileForm"
form={form}
onFinish={handleOnFinish}
onFinishFailed={handleOnFinishFailed}
>
{/* <Form.Item<ProfileProps>
{/* <Form.Item<ProfileProps>
name="username"
rules={[
{
@@ -76,53 +70,80 @@ const Profile: React.FC = () => {
style={{ width: INPUT_WIDTH.default }}
></SealInput.Input>
</Form.Item> */}
<Form.Item<ProfileProps>
name="current_password"
rules={[
{
required: true,
message: intl.formatMessage(
{ id: 'common.form.rule.input' },
{
name: intl.formatMessage({
id: 'users.form.currentpassword'
})
}
)
<Form.Item<ProfileProps>
name="current_password"
rules={[
{
required: true,
message: intl.formatMessage(
{ id: 'common.form.rule.input' },
{
name: intl.formatMessage({
id: 'users.form.currentpassword'
})
}
)
}
]}
>
<SealInput.Password
label={intl.formatMessage({ id: 'users.form.currentpassword' })}
required
style={{ width: INPUT_WIDTH.default }}
></SealInput.Password>
</Form.Item>
<Form.Item<ProfileProps>
name="new_password"
rules={[
{
required: true,
pattern: PasswordReg,
message: intl.formatMessage({
id: 'users.form.rule.password'
})
}
]}
>
<SealInput.Password
label={intl.formatMessage({ id: 'users.form.newpassword' })}
required
style={{ width: INPUT_WIDTH.default }}
></SealInput.Password>
</Form.Item>
<Form.Item
name="confirm_password"
dependencies={['new_password']}
rules={[
{
required: true,
message: intl.formatMessage({
id: 'users.password.confirm.empty'
})
},
({ getFieldValue }) => ({
validator(_, value) {
if (!value || getFieldValue('new_password') === value) {
return Promise.resolve();
}
return Promise.reject(
new Error(
intl.formatMessage({ id: 'users.password.confirm.error' })
)
);
}
]}
>
<SealInput.Password
label={intl.formatMessage({ id: 'users.form.currentpassword' })}
required
style={{ width: INPUT_WIDTH.default }}
></SealInput.Password>
</Form.Item>
<Form.Item<ProfileProps>
name="new_password"
rules={[
{
required: true,
pattern: PasswordReg,
message: intl.formatMessage({
id: 'users.form.rule.password'
})
}
]}
>
<SealInput.Password
label={intl.formatMessage({ id: 'users.form.newpassword' })}
required
style={{ width: INPUT_WIDTH.default }}
></SealInput.Password>
</Form.Item>
<FormButtons
htmlType="submit"
onCancel={handleCancel}
showCancel={false}
></FormButtons>
</Form>
</CardWrapper>
})
]}
>
<SealInput.Password
label={intl.formatMessage({ id: 'users.password.confirm' })}
/>
</Form.Item>
<FormButtons
htmlType="submit"
onCancel={handleCancel}
showCancel={false}
></FormButtons>
</Form>
</PageContainer>
</StrictMode>
);
+2 -2
View File
@@ -146,7 +146,7 @@ const Models: React.FC = () => {
}}
>
<Column
title={intl.formatMessage({ id: 'resources.table.hostname' })}
title={intl.formatMessage({ id: 'common.table.name' })}
dataIndex="hostname"
key="hostname"
/>
@@ -211,7 +211,7 @@ const Models: React.FC = () => {
key="GPU"
render={(text, record: ListItem) => {
return (
<span className="flex-column">
<span className="flex-column flex-gap-2">
{record?.status?.gpu_devices.map((item, index) => {
return (
<span className="flex-center" key={index}>
+2 -13
View File
@@ -3,11 +3,7 @@ import SealInput from '@/components/seal-form/seal-input';
import SealSelect from '@/components/seal-form/seal-select';
import { PageAction, PasswordReg } from '@/config';
import { PageActionType } from '@/config/types';
import {
SyncOutlined,
UserOutlined,
UserSwitchOutlined
} from '@ant-design/icons';
import { UserOutlined, UserSwitchOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Form, Modal, Select } from 'antd';
import { useEffect } from 'react';
@@ -32,14 +28,7 @@ const AddModal: React.FC<AddModalProps> = ({
}) => {
const [form] = Form.useForm();
const intl = useIntl();
const suffix = (
<SyncOutlined
style={{
fontSize: 16,
color: '#1677ff'
}}
/>
);
const initFormValue = () => {
if (action === PageAction.EDIT && open) {
form.setFieldsValue({
+5 -19
View File
@@ -113,7 +113,6 @@ const Models: React.FC = () => {
};
const handleModalOk = async (data: FormData) => {
console.log('handleModalOk');
const params = {
...data,
is_admin: data.is_admin === 'admin'
@@ -131,7 +130,7 @@ const Models: React.FC = () => {
}
fetchData();
setOpenAddModal(false);
message.success('');
message.success(intl.formatMessage({ id: 'common.message.success' }));
} catch (error) {
setOpenAddModal(false);
}
@@ -261,22 +260,9 @@ const Models: React.FC = () => {
}}
>
<Column
title={intl.formatMessage({ id: 'users.table.username' })}
title={intl.formatMessage({ id: 'common.table.name' })}
dataIndex="username"
key="name"
width={200}
/>
<Column
title={intl.formatMessage({ id: 'common.table.createTime' })}
dataIndex="created_at"
key="createTime"
defaultSortOrder="descend"
sortOrder={sortOrder}
showSorterTooltip={false}
sorter={true}
render={(text, record) => {
return dayjs(text).format('YYYY-MM-DD HH:mm:ss');
}}
/>
<Column
title={intl.formatMessage({ id: 'users.table.role' })}
@@ -301,9 +287,9 @@ const Models: React.FC = () => {
}}
/>
<Column
title={intl.formatMessage({ id: 'common.table.updateTime' })}
dataIndex="updated_at"
key="updateTime"
title={intl.formatMessage({ id: 'common.table.createTime' })}
dataIndex="created_at"
key="createTime"
defaultSortOrder="descend"
sortOrder={sortOrder}
showSorterTooltip={false}