fix: do not paste multiple lines
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 (
|
||||||
|
|||||||
@@ -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'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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 ==========
|
||||||
|
|||||||
@@ -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 ==========
|
||||||
|
|||||||
@@ -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,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);
|
||||||
|
|||||||
@@ -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
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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 (
|
||||||
|
|||||||
Reference in New Issue
Block a user