diff --git a/src/assets/styles/common.less b/src/assets/styles/common.less index 5aadef65..60af24d8 100644 --- a/src/assets/styles/common.less +++ b/src/assets/styles/common.less @@ -270,6 +270,10 @@ gap: 16px; } +.gap-4 { + gap: 4px; +} + .color-white-tertiary { color: var(--color-white-tertiary); } diff --git a/src/hooks/use-table-row-selection.ts b/src/hooks/use-table-row-selection.ts index 72cf04de..8cd366bb 100644 --- a/src/hooks/use-table-row-selection.ts +++ b/src/hooks/use-table-row-selection.ts @@ -41,6 +41,9 @@ export default function useTableRowSelection() { selectedRowKeys, selectedRows, enableSelection: true, + getCheckboxProps: (record: Record) => ({ + disabled: record.disabled + }), clearSelections, onChange: onSelectChange, removeSelectedKeys, diff --git a/src/locales/en-US/resources.ts b/src/locales/en-US/resources.ts index 4d423a87..0e3359a5 100644 --- a/src/locales/en-US/resources.ts +++ b/src/locales/en-US/resources.ts @@ -95,5 +95,6 @@ export default { 'resource.register.windows.support': 'win 10, win 11', 'resources.model.instance': 'Model Instance', 'resources.worker.download.privatekey': 'Download Private Key', - 'resources.modelfiles.form.exsting': 'Existing' + 'resources.modelfiles.form.exsting': 'Downloaded', + 'resources.modelfiles.form.added': 'Added' }; diff --git a/src/locales/ja-JP/resources.ts b/src/locales/ja-JP/resources.ts index e929ec0c..263f7b92 100644 --- a/src/locales/ja-JP/resources.ts +++ b/src/locales/ja-JP/resources.ts @@ -96,7 +96,8 @@ export default { 'resources.model.instance': 'Model Instance', 'resources.worker.download.privatekey': 'Download Private Key', 'resources.worker': 'Worker', - 'resources.modelfiles.form.exsting': 'Existing' + 'resources.modelfiles.form.exsting': 'Downloaded', + 'resources.modelfiles.form.added': 'Added' }; // ========== To-Do: Translate Keys (Remove After Translation) ========== @@ -115,5 +116,6 @@ export default { // 13. 'resources.model.instance': 'Model Instance', // 14. 'resources.worker.download.privatekey': 'Download Private Key', // 15. 'resources.worker': 'Worker', -// 16. 'resources.modelfiles.form.exsting': 'Existing' +// 16. 'resources.modelfiles.form.exsting': 'Downloaded', +// 17. 'resources.modelfiles.form.added': 'Added' // ========== End of To-Do List ========== diff --git a/src/locales/ru-RU/resources.ts b/src/locales/ru-RU/resources.ts index a3a91883..46f70006 100644 --- a/src/locales/ru-RU/resources.ts +++ b/src/locales/ru-RU/resources.ts @@ -94,9 +94,12 @@ export default { 'resources.model.instance': 'Модель экземпляра', 'resources.worker.download.privatekey': 'Скачать приватный ключ', 'resources.worker': 'Worker', - 'resources.modelfiles.form.exsting': 'Существующий' + 'resources.modelfiles.form.exsting': 'Downloaded', + 'resources.modelfiles.form.added': 'Added' }; // ========== To-Do: Translate Keys (Remove After Translation) ========== // 1. 'resources.worker': 'Worker', +// 2. 'resources.modelfiles.form.exsting': 'Downloaded', +// 3. 'resources.modelfiles.form.added': 'Added' // ========== End of To-Do List ========== diff --git a/src/locales/zh-CN/resources.ts b/src/locales/zh-CN/resources.ts index e125af0a..4ecc6101 100644 --- a/src/locales/zh-CN/resources.ts +++ b/src/locales/zh-CN/resources.ts @@ -93,5 +93,6 @@ export default { 'resource.register.windows.support': 'win 10, win 11', 'resources.model.instance': '模型实例', 'resources.worker.download.privatekey': '下载私钥', - 'resources.modelfiles.form.exsting': '已存在' + 'resources.modelfiles.form.exsting': '已下载', + 'resources.modelfiles.form.added': '已添加' }; diff --git a/src/pages/api-keys/components/add-apikey-modal/allow-models.tsx b/src/pages/api-keys/components/add-apikey-modal/allow-models.tsx index 78668879..9333f5c0 100644 --- a/src/pages/api-keys/components/add-apikey-modal/allow-models.tsx +++ b/src/pages/api-keys/components/add-apikey-modal/allow-models.tsx @@ -2,7 +2,7 @@ import { PageAction } from '@/config'; import { PageActionType } from '@/config/types'; import useAppUtils from '@/hooks/use-app-utils'; import SelectPanel from '@/pages/_components/select-panel'; -import { queryModelsList } from '@/pages/llmodels/apis'; +import { queryMyModels } from '@/pages/llmodels/apis'; import { useIntl } from '@umijs/max'; import { Divider, Form, Radio } from 'antd'; import { useEffect, useState } from 'react'; @@ -38,7 +38,7 @@ const AllowModelsForm: React.FC<{ const getModelList = async () => { try { - const res = await queryModelsList(queryParams); + const res = await queryMyModels(queryParams); const options = res.items.map((item) => item.name); if (action === PageAction.EDIT && currentData) { const list = new Set([ diff --git a/src/pages/llmodels/components/access-control-modal/form.tsx b/src/pages/llmodels/components/access-control-modal/form.tsx index c72517bc..97ff55d0 100644 --- a/src/pages/llmodels/components/access-control-modal/form.tsx +++ b/src/pages/llmodels/components/access-control-modal/form.tsx @@ -186,11 +186,11 @@ const AccessControlForm = forwardRef((props: AccessControlFormProps, ref) => { item.title.toLowerCase().includes(inputValue.toLowerCase()) } render={(item) => ( - + {item.title} {item.is_admin - ? `(${intl.formatMessage({ id: 'models.table.admin' })})` + ? `[${intl.formatMessage({ id: 'models.table.admin' })}]` : ''} diff --git a/src/pages/llmodels/download/target-form.tsx b/src/pages/llmodels/download/target-form.tsx index 7b840e88..d36ad902 100644 --- a/src/pages/llmodels/download/target-form.tsx +++ b/src/pages/llmodels/download/target-form.tsx @@ -52,6 +52,7 @@ const TargetForm: React.FC = forwardRef((props, ref) => { const { getRuleMessage } = useAppUtils(); const intl = useIntl(); const [form] = Form.useForm(); + const localPath = Form.useWatch('local_path', form); useEffect(() => { const init = async () => { @@ -95,18 +96,22 @@ const TargetForm: React.FC = forwardRef((props, ref) => { const isExisting = currentWorker?.children?.some((child) => { const isSameFile = - child.fileName === (fileName || '') || + child.fileName === (fileName || localPath || '') || minimatch(child.fileName || '', fileName || ''); - return child.repoId === selectedModel?.name && isSameFile; + return child.repoId === (selectedModel?.name || '') && isSameFile; }); + const localeId = localPath + ? 'resources.modelfiles.form.added' + : 'resources.modelfiles.form.exsting'; + return ( {data.label} {isExisting && ( - ({intl.formatMessage({ id: 'resources.modelfiles.form.exsting' })}) + [{intl.formatMessage({ id: localeId })}] )} diff --git a/src/pages/resources/components/model-files.tsx b/src/pages/resources/components/model-files.tsx index 917aa64e..aa1ad337 100644 --- a/src/pages/resources/components/model-files.tsx +++ b/src/pages/resources/components/model-files.tsx @@ -133,6 +133,7 @@ const ModelFiles = () => { ).pop() ); + // select the worker current model file is downloaded to. const targetWorker = _.find(workersList, { value: record.worker_id }) ?.labels?.['worker-name']; diff --git a/src/pages/users/hooks/use-users-columns.tsx b/src/pages/users/hooks/use-users-columns.tsx index 74a34440..90769bb3 100644 --- a/src/pages/users/hooks/use-users-columns.tsx +++ b/src/pages/users/hooks/use-users-columns.tsx @@ -3,7 +3,8 @@ import AutoTooltip from '@/components/auto-tooltip'; import DropdownButtons from '@/components/drop-down-buttons'; import IconFont from '@/components/icon-font'; import icons from '@/components/icon-font/icons'; -import { useIntl } from '@umijs/max'; +import { useIntl, useModel } from '@umijs/max'; +import { useMemoizedFn } from 'ahooks'; import { Tag } from 'antd'; import type { SortOrder } from 'antd/es/table/interface'; import { ColumnsType } from 'antd/lib/table'; @@ -35,6 +36,16 @@ const useUsersColumns = ({ sortOrder }: ColumnsHookProps): ColumnsType => { const intl = useIntl(); + const { initialState } = useModel('@@initialState') || {}; + + const setActions = useMemoizedFn((record: ListItem) => { + return actionList.filter((action) => { + if (initialState?.currentUser?.id === record.id) { + return action.key !== 'delete'; + } + return true; + }); + }); return useMemo(() => { return [ @@ -168,13 +179,13 @@ const useUsersColumns = ({ span: 3, render: (text, record) => ( handleSelect(val, record)} /> ) } ]; - }, [sortOrder, intl, handleSelect]); + }, [sortOrder, intl, handleSelect, setActions]); }; export default useUsersColumns; diff --git a/src/pages/users/index.tsx b/src/pages/users/index.tsx index a9c65066..54015128 100644 --- a/src/pages/users/index.tsx +++ b/src/pages/users/index.tsx @@ -5,10 +5,10 @@ import { PageAction } from '@/config'; import type { PageActionType } from '@/config/types'; import useTableFetch from '@/hooks/use-table-fetch'; import { PageContainer } from '@ant-design/pro-components'; -import { useIntl } from '@umijs/max'; +import { useIntl, useModel } from '@umijs/max'; import { useMemoizedFn } from 'ahooks'; import { Button, ConfigProvider, message, Table } from 'antd'; -import { useState } from 'react'; +import { useMemo, useState } from 'react'; import NoResult from '../_components/no-result'; import { createUser, deleteUser, queryUsersList, updateUser } from './apis'; import AddModal from './components/add-modal'; @@ -35,6 +35,7 @@ const Users: React.FC = () => { contentForDelete: 'users.table.user' }); + const { initialState } = useModel('@@initialState') || {}; const intl = useIntl(); const [openAddModalStatus, setOpenAddModalStatus] = useState<{ action: PageActionType; @@ -155,6 +156,13 @@ const Users: React.FC = () => { sortOrder }); + const dataList = useMemo(() => { + return dataSource.dataList.map((item) => ({ + ...item, + disabled: initialState?.currentUser?.id === item.id + })); + }, [dataSource.dataList, initialState?.currentUser?.id]); + return ( <> {