From 7334bcdf83f4a6b8828f7fa65980cfcf5f29df4d Mon Sep 17 00:00:00 2001 From: jialin Date: Thu, 6 Nov 2025 15:36:59 +0800 Subject: [PATCH] fix: do not paste multiple lines --- src/components/icon-font/icons.ts | 7 +++- src/components/icon-font/index.tsx | 2 +- src/components/label-selector/index.tsx | 25 ++++++++++---- src/locales/en-US/models.ts | 2 +- src/locales/en-US/users.ts | 4 ++- src/locales/ja-JP/users.ts | 8 +++-- src/locales/ru-RU/users.ts | 7 ++-- src/locales/zh-CN/users.ts | 4 ++- .../llmodels/components/instance-item.tsx | 4 +-- src/pages/llmodels/forms/advance-config.tsx | 12 +++---- src/pages/llmodels/forms/backend.tsx | 12 ++++--- src/pages/users/hooks/use-users-columns.tsx | 8 ++--- src/pages/users/index.tsx | 33 +++++++++++-------- 13 files changed, 81 insertions(+), 47 deletions(-) diff --git a/src/components/icon-font/icons.ts b/src/components/icon-font/icons.ts index 9e4e2a1a..c0ddce6b 100644 --- a/src/components/icon-font/icons.ts +++ b/src/components/icon-font/icons.ts @@ -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; diff --git a/src/components/icon-font/index.tsx b/src/components/icon-font/index.tsx index 858018cd..afb6996f 100644 --- a/src/components/icon-font/index.tsx +++ b/src/components/icon-font/index.tsx @@ -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; diff --git a/src/components/label-selector/index.tsx b/src/components/label-selector/index.tsx index 6a0a0aa7..17304cab 100644 --- a/src/components/label-selector/index.tsx +++ b/src/components/label-selector/index.tsx @@ -55,6 +55,20 @@ const LabelSelector: React.FC = ({ 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, index: number @@ -72,13 +86,12 @@ const LabelSelector: React.FC = ({ 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 ( diff --git a/src/locales/en-US/models.ts b/src/locales/en-US/models.ts index db9521d1..743b2684 100644 --- a/src/locales/en-US/models.ts +++ b/src/locales/en-US/models.ts @@ -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' }; diff --git a/src/locales/en-US/users.ts b/src/locales/en-US/users.ts index ec2a6595..01ee99f5 100644 --- a/src/locales/en-US/users.ts +++ b/src/locales/en-US/users.ts @@ -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' }; diff --git a/src/locales/ja-JP/users.ts b/src/locales/ja-JP/users.ts index 2f5e1e40..18232670 100644 --- a/src/locales/ja-JP/users.ts +++ b/src/locales/ja-JP/users.ts @@ -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 ========== diff --git a/src/locales/ru-RU/users.ts b/src/locales/ru-RU/users.ts index 1cbef673..d34572ba 100644 --- a/src/locales/ru-RU/users.ts +++ b/src/locales/ru-RU/users.ts @@ -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 ========== diff --git a/src/locales/zh-CN/users.ts b/src/locales/zh-CN/users.ts index 826092cd..70dbb579 100644 --- a/src/locales/zh-CN/users.ts +++ b/src/locales/zh-CN/users.ts @@ -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': '停用账户' }; diff --git a/src/pages/llmodels/components/instance-item.tsx b/src/pages/llmodels/components/instance-item.tsx index fdf22653..a8aac602 100644 --- a/src/pages/llmodels/components/instance-item.tsx +++ b/src/pages/llmodels/components/instance-item.tsx @@ -475,9 +475,7 @@ const InstanceItem: React.FC = ({
{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})` : ''}
diff --git a/src/pages/llmodels/forms/advance-config.tsx b/src/pages/llmodels/forms/advance-config.tsx index f050bc87..ab9c0930 100644 --- a/src/pages/llmodels/forms/advance-config.tsx +++ b/src/pages/llmodels/forms/advance-config.tsx @@ -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) => { - form.setFieldValue('env', labels); - }, - [] - ); + const handleEnviromentVarsChange = (labels: Record) => { + console.log('handleEnviromentVarsChange', labels); + form.setFieldValue('env', labels); + }; const onSelectorChange = (field: string, allowEmpty?: boolean) => { const workerSelector = form.getFieldValue(field); diff --git a/src/pages/llmodels/forms/backend.tsx b/src/pages/llmodels/forms/backend.tsx index 5f6bc9bb..d3c9d882 100644 --- a/src/pages/llmodels/forms/backend.tsx +++ b/src/pages/llmodels/forms/backend.tsx @@ -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 }); } diff --git a/src/pages/users/hooks/use-users-columns.tsx b/src/pages/users/hooks/use-users-columns.tsx index bf21bb86..c61b6ab3 100644 --- a/src/pages/users/hooks/use-users-columns.tsx +++ b/src/pages/users/hooks/use-users-columns.tsx @@ -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', diff --git a/src/pages/users/index.tsx b/src/pages/users/index.tsx index a1c05075..937dd71e 100644 --- a/src/pages/users/index.tsx +++ b/src/pages/users/index.tsx @@ -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 (