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' }), Version: React.createElement(IconFont, { type: 'icon-version' }),
Parameter: React.createElement(IconFont, { type: 'icon-parameters' }), Parameter: React.createElement(IconFont, { type: 'icon-parameters' }),
Private: React.createElement(IconFont, { type: 'icon-private' }), 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; export default icons;
+1 -1
View File
@@ -2,7 +2,7 @@ import { createFromIconfontCN } from '@ant-design/icons';
// import './iconfont/iconfont.js'; // import './iconfont/iconfont.js';
const IconFont = createFromIconfontCN({ 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; export default IconFont;
+19 -6
View File
@@ -55,6 +55,20 @@ const LabelSelector: React.FC<LabelSelectorProps> = ({
onChange?.(data); 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 = ( const handleOnPaste = (
e: React.ClipboardEvent<HTMLTextAreaElement>, e: React.ClipboardEvent<HTMLTextAreaElement>,
index: number index: number
@@ -72,13 +86,12 @@ const LabelSelector: React.FC<LabelSelectorProps> = ({
const [key, value] = line.split('=').map((part) => part.trim()); const [key, value] = line.split('=').map((part) => part.trim());
return { key, value }; return { key, value };
}); });
console.log('onPaste', lines, parsedData);
setLabelList((prevPairs) => { const newPairs = [...labelList];
const newPairs = [...prevPairs]; newPairs.splice(index, 1, ...parsedData);
newPairs.splice(index, 1, ...parsedData);
return newPairs; updateLabels(newPairs);
}); setLabelList(newPairs);
}; };
return ( return (
+1 -1
View File
@@ -238,5 +238,5 @@ export default {
'models.form.draftModel.tips': '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.', '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.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.login.title': 'Log in to',
'users.version.islatest': 'GPUStack {version} is the latest version', 'users.version.islatest': 'GPUStack {version} is the latest version',
'users.version.update': 'GPUStack {version} is available', '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.login.title': 'ログイン',
'users.version.islatest': 'GPUStack {version} は最新バージョンです', 'users.version.islatest': 'GPUStack {version} は最新バージョンです',
'users.version.update': '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) ========== // ========== 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 ========== // ========== End of To-Do List ==========
+5 -2
View File
@@ -35,9 +35,12 @@ export default {
'users.login.title': 'Вход в', 'users.login.title': 'Вход в',
'users.version.islatest': 'GPUStack {version} — последняя версия', 'users.version.islatest': 'GPUStack {version} — последняя версия',
'users.version.update': 'Доступно обновление 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) ========== // ========== To-Do: Translate Keys (Remove After Translation) ==========
// 1. 'users.status.activate': 'Activate Account',
// 2. 'users.status.deactivate': 'Deactivate Account',
// ========== End of To-Do List ========== // ========== End of To-Do List ==========
+3 -1
View File
@@ -33,5 +33,7 @@ export default {
'users.login.title': '登录', 'users.login.title': '登录',
'users.version.islatest': 'GPUStack {version} 已是最新版本', 'users.version.islatest': 'GPUStack {version} 已是最新版本',
'users.version.update': '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"> <div className="flex-center">
<ThunderboltFilled className="m-r-5" /> <ThunderboltFilled className="m-r-5" />
{intl.formatMessage({ id: 'models.form.backend' })}:{' '} {intl.formatMessage({ id: 'models.form.backend' })}:{' '}
{modelData?.backend === backendOptionsMap.custom {modelData?.backend || ''}
? intl.formatMessage({ id: 'models.form.backend.custom' })
: modelData?.backend || ''}
{modelData.backend_version ? `(${modelData.backend_version})` : ''} {modelData.backend_version ? `(${modelData.backend_version})` : ''}
</div> </div>
</div> </div>
+4 -8
View File
@@ -4,7 +4,6 @@ import SealSelect from '@/components/seal-form/seal-select';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Form } from 'antd'; import { Form } from 'antd';
import _ from 'lodash'; import _ from 'lodash';
import { useCallback } from 'react';
import { DeployFormKeyMap, modelCategories } from '../config'; import { DeployFormKeyMap, modelCategories } from '../config';
import { backendOptionsMap } from '../config/backend-parameters'; import { backendOptionsMap } from '../config/backend-parameters';
import { useFormContext } from '../config/form-context'; import { useFormContext } from '../config/form-context';
@@ -17,16 +16,13 @@ const AdvanceConfig = () => {
const intl = useIntl(); const intl = useIntl();
const form = Form.useFormInstance(); const form = Form.useFormInstance();
const EnviromentVars = Form.useWatch('env', form); const EnviromentVars = Form.useWatch('env', form);
const scheduleType = Form.useWatch('scheduleType', form);
const backend = Form.useWatch('backend', form); const backend = Form.useWatch('backend', form);
const { onValuesChange, formKey } = useFormContext(); const { onValuesChange, formKey } = useFormContext();
const handleEnviromentVarsChange = useCallback( const handleEnviromentVarsChange = (labels: Record<string, any>) => {
(labels: Record<string, any>) => { console.log('handleEnviromentVarsChange', labels);
form.setFieldValue('env', labels); form.setFieldValue('env', labels);
}, };
[]
);
const onSelectorChange = (field: string, allowEmpty?: boolean) => { const onSelectorChange = (field: string, allowEmpty?: boolean) => {
const workerSelector = form.getFieldValue(field); const workerSelector = form.getFieldValue(field);
+8 -4
View File
@@ -38,8 +38,12 @@ const BackendFields: React.FC = () => {
}, [backend]); }, [backend]);
const backendGroupedOptions = useMemo(() => { const backendGroupedOptions = useMemo(() => {
const builtInBackends = backendOptions?.filter((item) => item.isBuiltIn); const builtInBackends = backendOptions?.filter(
const customBackends = backendOptions?.filter((item) => !item.isBuiltIn); (item) => item.isBuiltIn || item.value === backendOptionsMap.custom
);
const customBackends = backendOptions?.filter(
(item) => !item.isBuiltIn && item.value !== backendOptionsMap.custom
);
const options = []; const options = [];
@@ -52,7 +56,7 @@ const BackendFields: React.FC = () => {
if (customBackends && customBackends.length > 0) { if (customBackends && customBackends.length > 0) {
options.push({ options.push({
label: intl.formatMessage({ id: 'backend.custom' }), label: intl.formatMessage({ id: 'models.form.backend.custom' }),
options: customBackends options: customBackends
}); });
} }
@@ -93,7 +97,7 @@ const BackendFields: React.FC = () => {
if (customVersions.length > 0) { if (customVersions.length > 0) {
options.push({ options.push({
label: intl.formatMessage({ id: 'backend.custom' }), label: intl.formatMessage({ id: 'models.form.backend.custom' }),
options: customVersions options: customVersions
}); });
} }
+4 -4
View File
@@ -24,14 +24,14 @@ const actionList: Global.ActionItem[] = [
icon: icons.EditOutlined icon: icons.EditOutlined
}, },
{ {
label: 'Active Account', label: 'users.status.activate',
key: 'active', key: 'active',
icon: icons.EditOutlined icon: icons.LockOpen
}, },
{ {
label: 'Deactivate Account', label: 'users.status.deactivate',
key: 'inactive', key: 'inactive',
icon: icons.EditOutlined icon: icons.LockPerson
}, },
{ {
label: 'common.button.delete', 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 { useMemo, useState } from 'react';
import NoResult from '../_components/no-result'; import NoResult from '../_components/no-result';
import PageBox from '../_components/page-box'; 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 AddModal from './components/add-modal';
import { FormData, ListItem } from './config/types'; import { FormData, ListItem } from './config/types';
import useUsersColumns from './hooks/use-users-columns'; 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) => { const handleActiveChange = async (checked: boolean, row: ListItem) => {
try { try {
await updateUser({ await updateUserStatus({
id: row.id,
data: { data: {
...row, is_active: checked
is_active: checked,
id: row?.id
} }
}); });
handleSearch(); 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) => { const renderEmpty = (type?: string) => {
if (type !== 'Table') return; if (type !== 'Table') return;
return ( return (