fix: do not paste multiple lines

This commit is contained in:
jialin
2025-11-06 15:37:42 +08:00
parent e1e38f0404
commit 7334bcdf83
13 changed files with 81 additions and 47 deletions
+6 -1
View File
@@ -51,7 +51,12 @@ const icons = {
Version: React.createElement(IconFont, { type: 'icon-version' }),
Parameter: React.createElement(IconFont, { type: 'icon-parameters' }),
Private: React.createElement(IconFont, { type: 'icon-private' }),
AWS: React.createElement(IconFont, { type: 'icon-aws' })
AWS: React.createElement(IconFont, { type: 'icon-aws' }),
LockOpenRight: React.createElement(IconFont, {
type: 'icon-lock_open_right'
}),
LockPerson: React.createElement(IconFont, { type: 'icon-lock_person' }),
LockOpen: React.createElement(IconFont, { type: 'icon-lock_open' })
};
export default icons;
+1 -1
View File
@@ -2,7 +2,7 @@ import { createFromIconfontCN } from '@ant-design/icons';
// import './iconfont/iconfont.js';
const IconFont = createFromIconfontCN({
scriptUrl: '//at.alicdn.com/t/c/font_4613488_nb1thiz3t9.js'
scriptUrl: '//at.alicdn.com/t/c/font_4613488_ipdaaask7g.js'
});
export default IconFont;
+19 -6
View File
@@ -55,6 +55,20 @@ const LabelSelector: React.FC<LabelSelectorProps> = ({
onChange?.(data);
};
const updateLabels = (list: { key: string; value: string }[]) => {
const newLabels = _.reduce(
list,
(result: any, item: any) => {
if (item.key) {
result[item.key] = item.value;
}
return result;
},
{}
);
onChange?.(newLabels);
};
const handleOnPaste = (
e: React.ClipboardEvent<HTMLTextAreaElement>,
index: number
@@ -72,13 +86,12 @@ const LabelSelector: React.FC<LabelSelectorProps> = ({
const [key, value] = line.split('=').map((part) => part.trim());
return { key, value };
});
console.log('onPaste', lines, parsedData);
setLabelList((prevPairs) => {
const newPairs = [...prevPairs];
newPairs.splice(index, 1, ...parsedData);
return newPairs;
});
const newPairs = [...labelList];
newPairs.splice(index, 1, ...parsedData);
updateLabels(newPairs);
setLabelList(newPairs);
};
return (
+1 -1
View File
@@ -238,5 +238,5 @@ export default {
'models.form.draftModel.tips':
'You can enter a local path (e.g., /path/to/model) or select a model from Hugging Face or ModelScope (e.g., Tengyunw/qwen3_8b_eagle3). The system will automatically match based on the primary model source.',
'models.form.quantization': 'Quantization',
'models.form.backend.custom': 'User Defined'
'models.form.backend.custom': 'User-defined'
};
+3 -1
View File
@@ -34,5 +34,7 @@ export default {
'users.login.title': 'Log in to',
'users.version.islatest': 'GPUStack {version} is the latest version',
'users.version.update': 'GPUStack {version} is available',
'users.settings.title': 'User Settings'
'users.settings.title': 'User Settings',
'users.status.activate': 'Activate Account',
'users.status.deactivate': 'Deactivate Account'
};
+6 -2
View File
@@ -35,9 +35,13 @@ export default {
'users.login.title': 'ログイン',
'users.version.islatest': 'GPUStack {version} は最新バージョンです',
'users.version.update': 'GPUStack {version} が利用可能です',
'users.settings.title': 'User Settings'
'users.settings.title': 'User Settings',
'users.status.activate': 'Activate Account',
'users.status.deactivate': 'Deactivate Account'
};
// ========== To-Do: Translate Keys (Remove After Translation) ==========
// 1. 'users.settings.title': 'User Settings'
// 1. 'users.settings.title': 'User Settings',
// 2. 'users.status.activate': 'Activate Account',
// 3. 'users.status.deactivate': 'Deactivate Account',
// ========== End of To-Do List ==========
+5 -2
View File
@@ -35,9 +35,12 @@ export default {
'users.login.title': 'Вход в',
'users.version.islatest': 'GPUStack {version} — последняя версия',
'users.version.update': 'Доступно обновление GPUStack {version}',
'users.settings.title': 'Настройки пользователя'
'users.settings.title': 'Настройки пользователя',
'users.status.activate': 'Activate Account',
'users.status.deactivate': 'Deactivate Account'
};
// ========== To-Do: Translate Keys (Remove After Translation) ==========
// 1. 'users.status.activate': 'Activate Account',
// 2. 'users.status.deactivate': 'Deactivate Account',
// ========== End of To-Do List ==========
+3 -1
View File
@@ -33,5 +33,7 @@ export default {
'users.login.title': '登录',
'users.version.islatest': 'GPUStack {version} 已是最新版本',
'users.version.update': 'GPUStack {version} 版本可供更新',
'users.settings.title': '用户设置'
'users.settings.title': '用户设置',
'users.status.activate': '启用账户',
'users.status.deactivate': '停用账户'
};
@@ -475,9 +475,7 @@ const InstanceItem: React.FC<InstanceItemProps> = ({
<div className="flex-center">
<ThunderboltFilled className="m-r-5" />
{intl.formatMessage({ id: 'models.form.backend' })}:{' '}
{modelData?.backend === backendOptionsMap.custom
? intl.formatMessage({ id: 'models.form.backend.custom' })
: modelData?.backend || ''}
{modelData?.backend || ''}
{modelData.backend_version ? `(${modelData.backend_version})` : ''}
</div>
</div>
+4 -8
View File
@@ -4,7 +4,6 @@ import SealSelect from '@/components/seal-form/seal-select';
import { useIntl } from '@umijs/max';
import { Form } from 'antd';
import _ from 'lodash';
import { useCallback } from 'react';
import { DeployFormKeyMap, modelCategories } from '../config';
import { backendOptionsMap } from '../config/backend-parameters';
import { useFormContext } from '../config/form-context';
@@ -17,16 +16,13 @@ const AdvanceConfig = () => {
const intl = useIntl();
const form = Form.useFormInstance();
const EnviromentVars = Form.useWatch('env', form);
const scheduleType = Form.useWatch('scheduleType', form);
const backend = Form.useWatch('backend', form);
const { onValuesChange, formKey } = useFormContext();
const handleEnviromentVarsChange = useCallback(
(labels: Record<string, any>) => {
form.setFieldValue('env', labels);
},
[]
);
const handleEnviromentVarsChange = (labels: Record<string, any>) => {
console.log('handleEnviromentVarsChange', labels);
form.setFieldValue('env', labels);
};
const onSelectorChange = (field: string, allowEmpty?: boolean) => {
const workerSelector = form.getFieldValue(field);
+8 -4
View File
@@ -38,8 +38,12 @@ const BackendFields: React.FC = () => {
}, [backend]);
const backendGroupedOptions = useMemo(() => {
const builtInBackends = backendOptions?.filter((item) => item.isBuiltIn);
const customBackends = backendOptions?.filter((item) => !item.isBuiltIn);
const builtInBackends = backendOptions?.filter(
(item) => item.isBuiltIn || item.value === backendOptionsMap.custom
);
const customBackends = backendOptions?.filter(
(item) => !item.isBuiltIn && item.value !== backendOptionsMap.custom
);
const options = [];
@@ -52,7 +56,7 @@ const BackendFields: React.FC = () => {
if (customBackends && customBackends.length > 0) {
options.push({
label: intl.formatMessage({ id: 'backend.custom' }),
label: intl.formatMessage({ id: 'models.form.backend.custom' }),
options: customBackends
});
}
@@ -93,7 +97,7 @@ const BackendFields: React.FC = () => {
if (customVersions.length > 0) {
options.push({
label: intl.formatMessage({ id: 'backend.custom' }),
label: intl.formatMessage({ id: 'models.form.backend.custom' }),
options: customVersions
});
}
+4 -4
View File
@@ -24,14 +24,14 @@ const actionList: Global.ActionItem[] = [
icon: icons.EditOutlined
},
{
label: 'Active Account',
label: 'users.status.activate',
key: 'active',
icon: icons.EditOutlined
icon: icons.LockOpen
},
{
label: 'Deactivate Account',
label: 'users.status.deactivate',
key: 'inactive',
icon: icons.EditOutlined
icon: icons.LockPerson
},
{
label: 'common.button.delete',
+20 -13
View File
@@ -10,7 +10,13 @@ import { Button, ConfigProvider, message, Table } from 'antd';
import { useMemo, useState } from 'react';
import NoResult from '../_components/no-result';
import PageBox from '../_components/page-box';
import { createUser, deleteUser, queryUsersList, updateUser } from './apis';
import {
createUser,
deleteUser,
queryUsersList,
updateUser,
updateUserStatus
} from './apis';
import AddModal from './components/add-modal';
import { FormData, ListItem } from './config/types';
import useUsersColumns from './hooks/use-users-columns';
@@ -105,21 +111,12 @@ const Users: React.FC = () => {
});
};
const handleSelect = useMemoizedFn((val: any, row: ListItem) => {
if (val === 'edit') {
handleEditUser(row);
} else if (val === 'delete') {
handleDelete({ ...row, name: row.username });
}
});
const handleActiveChange = async (checked: boolean, row: ListItem) => {
try {
await updateUser({
await updateUserStatus({
id: row.id,
data: {
...row,
is_active: checked,
id: row?.id
is_active: checked
}
});
handleSearch();
@@ -129,6 +126,16 @@ const Users: React.FC = () => {
}
};
const handleSelect = useMemoizedFn((val: any, row: ListItem) => {
if (val === 'edit') {
handleEditUser(row);
} else if (val === 'delete') {
handleDelete({ ...row, name: row.username });
} else if (val === 'active' || val === 'inactive') {
handleActiveChange(val === 'active', row);
}
});
const renderEmpty = (type?: string) => {
if (type !== 'Table') return;
return (