fix: admin can not delete own
This commit is contained in:
@@ -270,6 +270,10 @@
|
|||||||
gap: 16px;
|
gap: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gap-4 {
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
.color-white-tertiary {
|
.color-white-tertiary {
|
||||||
color: var(--color-white-tertiary);
|
color: var(--color-white-tertiary);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ export default function useTableRowSelection() {
|
|||||||
selectedRowKeys,
|
selectedRowKeys,
|
||||||
selectedRows,
|
selectedRows,
|
||||||
enableSelection: true,
|
enableSelection: true,
|
||||||
|
getCheckboxProps: (record: Record<string, any>) => ({
|
||||||
|
disabled: record.disabled
|
||||||
|
}),
|
||||||
clearSelections,
|
clearSelections,
|
||||||
onChange: onSelectChange,
|
onChange: onSelectChange,
|
||||||
removeSelectedKeys,
|
removeSelectedKeys,
|
||||||
|
|||||||
@@ -95,5 +95,6 @@ export default {
|
|||||||
'resource.register.windows.support': 'win 10, win 11',
|
'resource.register.windows.support': 'win 10, win 11',
|
||||||
'resources.model.instance': 'Model Instance',
|
'resources.model.instance': 'Model Instance',
|
||||||
'resources.worker.download.privatekey': 'Download Private Key',
|
'resources.worker.download.privatekey': 'Download Private Key',
|
||||||
'resources.modelfiles.form.exsting': 'Existing'
|
'resources.modelfiles.form.exsting': 'Downloaded',
|
||||||
|
'resources.modelfiles.form.added': 'Added'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -96,7 +96,8 @@ export default {
|
|||||||
'resources.model.instance': 'Model Instance',
|
'resources.model.instance': 'Model Instance',
|
||||||
'resources.worker.download.privatekey': 'Download Private Key',
|
'resources.worker.download.privatekey': 'Download Private Key',
|
||||||
'resources.worker': 'Worker',
|
'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) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
@@ -115,5 +116,6 @@ export default {
|
|||||||
// 13. 'resources.model.instance': 'Model Instance',
|
// 13. 'resources.model.instance': 'Model Instance',
|
||||||
// 14. 'resources.worker.download.privatekey': 'Download Private Key',
|
// 14. 'resources.worker.download.privatekey': 'Download Private Key',
|
||||||
// 15. 'resources.worker': 'Worker',
|
// 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 ==========
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -94,9 +94,12 @@ export default {
|
|||||||
'resources.model.instance': 'Модель экземпляра',
|
'resources.model.instance': 'Модель экземпляра',
|
||||||
'resources.worker.download.privatekey': 'Скачать приватный ключ',
|
'resources.worker.download.privatekey': 'Скачать приватный ключ',
|
||||||
'resources.worker': 'Worker',
|
'resources.worker': 'Worker',
|
||||||
'resources.modelfiles.form.exsting': 'Существующий'
|
'resources.modelfiles.form.exsting': 'Downloaded',
|
||||||
|
'resources.modelfiles.form.added': 'Added'
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
// 1. 'resources.worker': 'Worker',
|
// 1. 'resources.worker': 'Worker',
|
||||||
|
// 2. 'resources.modelfiles.form.exsting': 'Downloaded',
|
||||||
|
// 3. 'resources.modelfiles.form.added': 'Added'
|
||||||
// ========== End of To-Do List ==========
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -93,5 +93,6 @@ export default {
|
|||||||
'resource.register.windows.support': 'win 10, win 11',
|
'resource.register.windows.support': 'win 10, win 11',
|
||||||
'resources.model.instance': '模型实例',
|
'resources.model.instance': '模型实例',
|
||||||
'resources.worker.download.privatekey': '下载私钥',
|
'resources.worker.download.privatekey': '下载私钥',
|
||||||
'resources.modelfiles.form.exsting': '已存在'
|
'resources.modelfiles.form.exsting': '已下载',
|
||||||
|
'resources.modelfiles.form.added': '已添加'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { PageAction } from '@/config';
|
|||||||
import { PageActionType } from '@/config/types';
|
import { PageActionType } from '@/config/types';
|
||||||
import useAppUtils from '@/hooks/use-app-utils';
|
import useAppUtils from '@/hooks/use-app-utils';
|
||||||
import SelectPanel from '@/pages/_components/select-panel';
|
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 { useIntl } from '@umijs/max';
|
||||||
import { Divider, Form, Radio } from 'antd';
|
import { Divider, Form, Radio } from 'antd';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
@@ -38,7 +38,7 @@ const AllowModelsForm: React.FC<{
|
|||||||
|
|
||||||
const getModelList = async () => {
|
const getModelList = async () => {
|
||||||
try {
|
try {
|
||||||
const res = await queryModelsList(queryParams);
|
const res = await queryMyModels(queryParams);
|
||||||
const options = res.items.map((item) => item.name);
|
const options = res.items.map((item) => item.name);
|
||||||
if (action === PageAction.EDIT && currentData) {
|
if (action === PageAction.EDIT && currentData) {
|
||||||
const list = new Set([
|
const list = new Set([
|
||||||
|
|||||||
@@ -186,11 +186,11 @@ const AccessControlForm = forwardRef((props: AccessControlFormProps, ref) => {
|
|||||||
item.title.toLowerCase().includes(inputValue.toLowerCase())
|
item.title.toLowerCase().includes(inputValue.toLowerCase())
|
||||||
}
|
}
|
||||||
render={(item) => (
|
render={(item) => (
|
||||||
<span className="flex-center gap-8">
|
<span className="flex-center gap-4">
|
||||||
<span>{item.title}</span>
|
<span>{item.title}</span>
|
||||||
<span className="text-tertiary">
|
<span className="text-tertiary">
|
||||||
{item.is_admin
|
{item.is_admin
|
||||||
? `(${intl.formatMessage({ id: 'models.table.admin' })})`
|
? `[${intl.formatMessage({ id: 'models.table.admin' })}]`
|
||||||
: ''}
|
: ''}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ const TargetForm: React.FC<TargetFormProps> = forwardRef((props, ref) => {
|
|||||||
const { getRuleMessage } = useAppUtils();
|
const { getRuleMessage } = useAppUtils();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
const localPath = Form.useWatch('local_path', form);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const init = async () => {
|
const init = async () => {
|
||||||
@@ -95,18 +96,22 @@ const TargetForm: React.FC<TargetFormProps> = forwardRef((props, ref) => {
|
|||||||
|
|
||||||
const isExisting = currentWorker?.children?.some((child) => {
|
const isExisting = currentWorker?.children?.some((child) => {
|
||||||
const isSameFile =
|
const isSameFile =
|
||||||
child.fileName === (fileName || '') ||
|
child.fileName === (fileName || localPath || '') ||
|
||||||
minimatch(child.fileName || '', fileName || '');
|
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 (
|
return (
|
||||||
<span>
|
<span>
|
||||||
{data.label}
|
{data.label}
|
||||||
{isExisting && (
|
{isExisting && (
|
||||||
<span className="text-tertiary m-l-4">
|
<span className="text-tertiary m-l-4">
|
||||||
({intl.formatMessage({ id: 'resources.modelfiles.form.exsting' })})
|
[{intl.formatMessage({ id: localeId })}]
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ const ModelFiles = () => {
|
|||||||
).pop()
|
).pop()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// select the worker current model file is downloaded to.
|
||||||
const targetWorker = _.find(workersList, { value: record.worker_id })
|
const targetWorker = _.find(workersList, { value: record.worker_id })
|
||||||
?.labels?.['worker-name'];
|
?.labels?.['worker-name'];
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ import AutoTooltip from '@/components/auto-tooltip';
|
|||||||
import DropdownButtons from '@/components/drop-down-buttons';
|
import DropdownButtons from '@/components/drop-down-buttons';
|
||||||
import IconFont from '@/components/icon-font';
|
import IconFont from '@/components/icon-font';
|
||||||
import icons from '@/components/icon-font/icons';
|
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 { Tag } from 'antd';
|
||||||
import type { SortOrder } from 'antd/es/table/interface';
|
import type { SortOrder } from 'antd/es/table/interface';
|
||||||
import { ColumnsType } from 'antd/lib/table';
|
import { ColumnsType } from 'antd/lib/table';
|
||||||
@@ -35,6 +36,16 @@ const useUsersColumns = ({
|
|||||||
sortOrder
|
sortOrder
|
||||||
}: ColumnsHookProps): ColumnsType<ListItem> => {
|
}: ColumnsHookProps): ColumnsType<ListItem> => {
|
||||||
const intl = useIntl();
|
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 useMemo(() => {
|
||||||
return [
|
return [
|
||||||
@@ -168,13 +179,13 @@ const useUsersColumns = ({
|
|||||||
span: 3,
|
span: 3,
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<DropdownButtons
|
<DropdownButtons
|
||||||
items={actionList}
|
items={setActions(record)}
|
||||||
onSelect={(val) => handleSelect(val, record)}
|
onSelect={(val) => handleSelect(val, record)}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}, [sortOrder, intl, handleSelect]);
|
}, [sortOrder, intl, handleSelect, setActions]);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useUsersColumns;
|
export default useUsersColumns;
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import { PageAction } from '@/config';
|
|||||||
import type { PageActionType } from '@/config/types';
|
import type { PageActionType } from '@/config/types';
|
||||||
import useTableFetch from '@/hooks/use-table-fetch';
|
import useTableFetch from '@/hooks/use-table-fetch';
|
||||||
import { PageContainer } from '@ant-design/pro-components';
|
import { PageContainer } from '@ant-design/pro-components';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl, useModel } from '@umijs/max';
|
||||||
import { useMemoizedFn } from 'ahooks';
|
import { useMemoizedFn } from 'ahooks';
|
||||||
import { Button, ConfigProvider, message, Table } from 'antd';
|
import { Button, ConfigProvider, message, Table } from 'antd';
|
||||||
import { useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
import NoResult from '../_components/no-result';
|
import NoResult from '../_components/no-result';
|
||||||
import { createUser, deleteUser, queryUsersList, updateUser } from './apis';
|
import { createUser, deleteUser, queryUsersList, updateUser } from './apis';
|
||||||
import AddModal from './components/add-modal';
|
import AddModal from './components/add-modal';
|
||||||
@@ -35,6 +35,7 @@ const Users: React.FC = () => {
|
|||||||
contentForDelete: 'users.table.user'
|
contentForDelete: 'users.table.user'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { initialState } = useModel('@@initialState') || {};
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const [openAddModalStatus, setOpenAddModalStatus] = useState<{
|
const [openAddModalStatus, setOpenAddModalStatus] = useState<{
|
||||||
action: PageActionType;
|
action: PageActionType;
|
||||||
@@ -155,6 +156,13 @@ const Users: React.FC = () => {
|
|||||||
sortOrder
|
sortOrder
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const dataList = useMemo(() => {
|
||||||
|
return dataSource.dataList.map((item) => ({
|
||||||
|
...item,
|
||||||
|
disabled: initialState?.currentUser?.id === item.id
|
||||||
|
}));
|
||||||
|
}, [dataSource.dataList, initialState?.currentUser?.id]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageContainer
|
<PageContainer
|
||||||
@@ -182,7 +190,7 @@ const Users: React.FC = () => {
|
|||||||
<ConfigProvider renderEmpty={renderEmpty}>
|
<ConfigProvider renderEmpty={renderEmpty}>
|
||||||
<Table
|
<Table
|
||||||
columns={columns}
|
columns={columns}
|
||||||
dataSource={dataSource.dataList}
|
dataSource={dataList}
|
||||||
rowSelection={rowSelection}
|
rowSelection={rowSelection}
|
||||||
loading={dataSource.loading}
|
loading={dataSource.loading}
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
|
|||||||
Reference in New Issue
Block a user