chore: update locales
This commit is contained in:
@@ -12,5 +12,8 @@ export default {
|
|||||||
'apikeys.form.expiration.1month': '1 month',
|
'apikeys.form.expiration.1month': '1 month',
|
||||||
'apikeys.form.expiration.6months': '6 months',
|
'apikeys.form.expiration.6months': '6 months',
|
||||||
'apikeys.form.expiration.never': 'No expiration',
|
'apikeys.form.expiration.never': 'No expiration',
|
||||||
'apikeys.table.bindModels': 'Allowed Models'
|
'apikeys.table.bindModels': 'Model Access',
|
||||||
|
'apikeys.models.all': 'All models',
|
||||||
|
'apikeys.models.selected': 'Selected models',
|
||||||
|
'apikeys.models.noModelsFound': 'No models found'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -170,5 +170,16 @@ export default {
|
|||||||
'models.form.enableSpeculativeDecoding': 'Enable Speculative Decoding',
|
'models.form.enableSpeculativeDecoding': 'Enable Speculative Decoding',
|
||||||
'models.form.check.clusterUnavailable': 'Current cluster is unavailable',
|
'models.form.check.clusterUnavailable': 'Current cluster is unavailable',
|
||||||
'models.form.check.otherClustersAvailable':
|
'models.form.check.otherClustersAvailable':
|
||||||
'Available clusters: {clusters}. Please switch cluster.'
|
'Available clusters: {clusters}. Please switch cluster.',
|
||||||
|
'models.button.accessSettings': 'Access Settings',
|
||||||
|
'models.table.accessScope': 'Access Scope',
|
||||||
|
'models.table.accessScope.all': 'All users',
|
||||||
|
'models.table.accessScope.selected': 'Selected users',
|
||||||
|
'models.table.userSelection': 'User Selection',
|
||||||
|
'models.table.filterByName': 'Filter by username',
|
||||||
|
'models.table.admin': 'Admin',
|
||||||
|
'models.table.noselected': 'No users selected',
|
||||||
|
'models.table.users.all': 'All Users',
|
||||||
|
'models.table.users.selected': 'Selected Users',
|
||||||
|
'models.table.nouserFound': 'No users found'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,5 +12,15 @@ export default {
|
|||||||
'apikeys.form.expiration.1month': '1ヶ月',
|
'apikeys.form.expiration.1month': '1ヶ月',
|
||||||
'apikeys.form.expiration.6months': '6ヶ月',
|
'apikeys.form.expiration.6months': '6ヶ月',
|
||||||
'apikeys.form.expiration.never': '無期限',
|
'apikeys.form.expiration.never': '無期限',
|
||||||
'apikeys.table.bindModels': '許可されたモデル'
|
'apikeys.table.bindModels': 'Model Access',
|
||||||
|
'apikeys.models.all': 'All models',
|
||||||
|
'apikeys.models.selected': 'Selected models',
|
||||||
|
'apikeys.models.noModelsFound': 'No models found'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
|
// 1. 'apikeys.table.bindModels': 'Model Access',
|
||||||
|
// 2. 'apikeys.models.all': 'All models',
|
||||||
|
// 3. 'apikeys.models.selected': 'Selected models',
|
||||||
|
// 4. 'apikeys.models.noModelsFound': 'No models found'
|
||||||
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -167,7 +167,18 @@ export default {
|
|||||||
'models.form.enableSpeculativeDecoding': '推測デコーディングを有効にする',
|
'models.form.enableSpeculativeDecoding': '推測デコーディングを有効にする',
|
||||||
'models.form.check.clusterUnavailable': 'Current cluster is unavailable',
|
'models.form.check.clusterUnavailable': 'Current cluster is unavailable',
|
||||||
'models.form.check.otherClustersAvailable':
|
'models.form.check.otherClustersAvailable':
|
||||||
'Available clusters: {clusters}. Please switch cluster.'
|
'Available clusters: {clusters}. Please switch cluster.',
|
||||||
|
'models.button.accessSettings': 'Access Settings',
|
||||||
|
'models.table.accessScope': 'Access Scope',
|
||||||
|
'models.table.accessScope.all': 'All users',
|
||||||
|
'models.table.accessScope.selected': 'Selected users',
|
||||||
|
'models.table.userSelection': 'User Selection',
|
||||||
|
'models.table.filterByName': 'Filter by username',
|
||||||
|
'models.table.admin': 'Admin',
|
||||||
|
'models.table.noselected': 'No users selected',
|
||||||
|
'models.table.users.all': 'All Users',
|
||||||
|
'models.table.users.selected': 'Selected Users',
|
||||||
|
'models.table.nouserFound': 'No users found'
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
@@ -175,5 +186,19 @@ export default {
|
|||||||
// 2. 'models.ollama.deprecated.notice': `The Ollama model source has been deprecated as of v0.6.1. For more information, see the <a href="https://github.com/gpustack/gpustack/issues/1979" target="_blank">related GitHub issue</a>.`
|
// 2. 'models.ollama.deprecated.notice': `The Ollama model source has been deprecated as of v0.6.1. For more information, see the <a href="https://github.com/gpustack/gpustack/issues/1979" target="_blank">related GitHub issue</a>.`
|
||||||
// 3. 'models.backend.mindie.310p':'Ascend 310P only supports FP16, so you need to set --dtype=float16.',
|
// 3. 'models.backend.mindie.310p':'Ascend 310P only supports FP16, so you need to set --dtype=float16.',
|
||||||
// 4. 'models.form.check.clusterUnavailable': 'Current cluster is unavailable',
|
// 4. 'models.form.check.clusterUnavailable': 'Current cluster is unavailable',
|
||||||
// 5. 'models.form.check.otherClustersAvailable': 'Available clusters: {clusters}. Please switch cluster.'
|
// 5. 'models.form.check.otherClustersAvailable': 'Available clusters: {clusters}. Please switch cluster.',
|
||||||
|
// 6. 'models.button.accessSettings': 'Access Settings',
|
||||||
|
// 7. 'models.table.accessScope': 'Access Scope',
|
||||||
|
// 8. 'models.table.accessScope.all': 'All users',
|
||||||
|
// 9. 'models.table.accessScope.selected': 'Selected users',
|
||||||
|
// 10. 'models.table.userSelection': 'User Selection',
|
||||||
|
// 11. 'models.table.filterByName': 'Filter by username',
|
||||||
|
// 12. 'models.table.admin': 'Admin',
|
||||||
|
// 13. 'models.table.noselected': 'No users selected'
|
||||||
|
// 14. 'models.table.uses.all': 'All users',
|
||||||
|
// 15. 'models.table.uses.selected': 'Selected users',
|
||||||
|
// 16. 'models.table.nouserFound': 'No users found',
|
||||||
|
// 17. 'models.table.users.all': 'All Users',
|
||||||
|
// 18. 'models.table.users.selected': 'Selected Users',
|
||||||
|
// 19. 'models.table.nouserFound': 'No users found'
|
||||||
// ========== End of To-Do List ==========
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -12,5 +12,15 @@ export default {
|
|||||||
'apikeys.form.expiration.1month': '1 месяц',
|
'apikeys.form.expiration.1month': '1 месяц',
|
||||||
'apikeys.form.expiration.6months': '6 месяцев',
|
'apikeys.form.expiration.6months': '6 месяцев',
|
||||||
'apikeys.form.expiration.never': 'Без срока действия',
|
'apikeys.form.expiration.never': 'Без срока действия',
|
||||||
'apikeys.table.bindModels': 'Разрешенные модели'
|
'apikeys.table.bindModels': 'Доступ к моделям',
|
||||||
|
'apikeys.models.all': 'All models',
|
||||||
|
'apikeys.models.selected': 'Selected models',
|
||||||
|
'apikeys.models.noModelsFound': 'No models found'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
|
// 1. 'apikeys.table.bindModels': 'Model Access',
|
||||||
|
// 2. 'apikeys.models.all': 'All models',
|
||||||
|
// 3. 'apikeys.models.selected': 'Selected models',
|
||||||
|
// 4. 'apikeys.models.noModelsFound': 'No models found'
|
||||||
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -166,12 +166,34 @@ export default {
|
|||||||
'models.form.gpuCount': 'GPU на реплику',
|
'models.form.gpuCount': 'GPU на реплику',
|
||||||
'models.form.gpuType': 'Тип GPU',
|
'models.form.gpuType': 'Тип GPU',
|
||||||
'models.form.optimizeLongPrompt': 'Оптимизировать длинные промпты',
|
'models.form.optimizeLongPrompt': 'Оптимизировать длинные промпты',
|
||||||
'models.form.enableSpeculativeDecoding': 'Включить спекулятивное декодирование',
|
'models.form.enableSpeculativeDecoding':
|
||||||
|
'Включить спекулятивное декодирование',
|
||||||
'models.form.check.clusterUnavailable': 'Текущий кластер недоступен',
|
'models.form.check.clusterUnavailable': 'Текущий кластер недоступен',
|
||||||
'models.form.check.otherClustersAvailable':
|
'models.form.check.otherClustersAvailable':
|
||||||
'Доступные кластеры: {clusters}. Пожалуйста, переключитесь на другой кластер.'
|
'Доступные кластеры: {clusters}. Пожалуйста, переключитесь на другой кластер.',
|
||||||
|
'models.button.accessSettings': 'Access Settings',
|
||||||
|
'models.table.accessScope': 'Access Scope',
|
||||||
|
'models.table.accessScope.all': 'All users',
|
||||||
|
'models.table.accessScope.selected': 'Selected users',
|
||||||
|
'models.table.userSelection': 'User Selection',
|
||||||
|
'models.table.filterByName': 'Filter by username',
|
||||||
|
'models.table.admin': 'Admin',
|
||||||
|
'models.table.noselected': 'No users selected',
|
||||||
|
'models.table.users.all': 'All users',
|
||||||
|
'models.table.users.selected': 'Selected users',
|
||||||
|
'models.table.nouserFound': 'No users found'
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
|
// 1. 'models.button.accessSettings': 'Access Settings',
|
||||||
|
// 2. 'models.table.accessScope': 'Access Scope',
|
||||||
|
// 3. 'models.table.accessScope.all': 'All users',
|
||||||
|
// 4. 'models.table.accessScope.selected': 'Selected users',
|
||||||
|
// 5. 'models.table.userSelection': 'User Selection',
|
||||||
|
// 6. 'models.table.filterByName': 'Filter by username',
|
||||||
|
// 7. 'models.table.admin': 'Admin',
|
||||||
|
// 8. 'models.table.noselected': 'No users selected',
|
||||||
|
// 9. 'models.table.users.all': 'All users',
|
||||||
|
// 10. 'models.table.users.selected': 'Selected users',
|
||||||
|
// 11. 'models.table.nouserFound': 'No users found'
|
||||||
// ========== End of To-Do List ==========
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -11,5 +11,8 @@ export default {
|
|||||||
'apikeys.form.expiration.1month': '1个月',
|
'apikeys.form.expiration.1month': '1个月',
|
||||||
'apikeys.form.expiration.6months': '6个月',
|
'apikeys.form.expiration.6months': '6个月',
|
||||||
'apikeys.form.expiration.never': '永不过期',
|
'apikeys.form.expiration.never': '永不过期',
|
||||||
'apikeys.table.bindModels': '绑定模型'
|
'apikeys.table.bindModels': '模型访问',
|
||||||
|
'apikeys.models.all': '所有模型',
|
||||||
|
'apikeys.models.selected': '指定模型',
|
||||||
|
'apikeys.models.noModelsFound': '未找到模型'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -160,5 +160,16 @@ export default {
|
|||||||
'models.form.enableSpeculativeDecoding': '启用推测解码',
|
'models.form.enableSpeculativeDecoding': '启用推测解码',
|
||||||
'models.form.check.clusterUnavailable': '当前集群不可用',
|
'models.form.check.clusterUnavailable': '当前集群不可用',
|
||||||
'models.form.check.otherClustersAvailable':
|
'models.form.check.otherClustersAvailable':
|
||||||
'可用的集群有: {clusters}。请切换集群。'
|
'可用的集群有: {clusters}。请切换集群。',
|
||||||
|
'models.button.accessSettings': '访问设置',
|
||||||
|
'models.table.accessScope': '访问范围',
|
||||||
|
'models.table.accessScope.all': '所有用户',
|
||||||
|
'models.table.accessScope.selected': '指定用户',
|
||||||
|
'models.table.userSelection': '用户选择',
|
||||||
|
'models.table.filterByName': '按用户名筛选',
|
||||||
|
'models.table.admin': '管理员',
|
||||||
|
'models.table.noselected': '未选择用户',
|
||||||
|
'models.table.users.all': '所有用户',
|
||||||
|
'models.table.users.selected': '已选用户',
|
||||||
|
'models.table.nouserFound': '未找到用户'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { SearchOutlined } from '@ant-design/icons';
|
import { SearchOutlined } from '@ant-design/icons';
|
||||||
|
import { useIntl } from '@umijs/max';
|
||||||
import { Button, Checkbox, Empty, Input } from 'antd';
|
import { Button, Checkbox, Empty, Input } from 'antd';
|
||||||
import React, { useEffect, useMemo, useState } from 'react';
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
@@ -34,6 +35,7 @@ interface SelectPanelProps {
|
|||||||
leftWidth?: number;
|
leftWidth?: number;
|
||||||
options: Array<{ key: string; title: string }>;
|
options: Array<{ key: string; title: string }>;
|
||||||
selectedKeys: string[];
|
selectedKeys: string[];
|
||||||
|
notFoundContent?: React.ReactNode;
|
||||||
onSelectChange: (selectedKeys: string[]) => void;
|
onSelectChange: (selectedKeys: string[]) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,8 +45,10 @@ const SelectPanel: React.FC<SelectPanelProps> = ({
|
|||||||
options,
|
options,
|
||||||
selectedKeys,
|
selectedKeys,
|
||||||
searchPlaceholder,
|
searchPlaceholder,
|
||||||
|
notFoundContent,
|
||||||
onSelectChange
|
onSelectChange
|
||||||
}) => {
|
}) => {
|
||||||
|
const intl = useIntl();
|
||||||
const [indeterminate, setIndeterminate] = React.useState(false);
|
const [indeterminate, setIndeterminate] = React.useState(false);
|
||||||
const [checkAll, setCheckAll] = React.useState(false);
|
const [checkAll, setCheckAll] = React.useState(false);
|
||||||
const [searchText, setSearchText] = useState('');
|
const [searchText, setSearchText] = useState('');
|
||||||
@@ -162,7 +166,12 @@ const SelectPanel: React.FC<SelectPanelProps> = ({
|
|||||||
indeterminate={indeterminate}
|
indeterminate={indeterminate}
|
||||||
onChange={handleCheckAllChange}
|
onChange={handleCheckAllChange}
|
||||||
></Checkbox>
|
></Checkbox>
|
||||||
<span> {selectedKeys.length} selected</span>
|
<span>
|
||||||
|
{intl.formatMessage(
|
||||||
|
{ id: 'common.select.count' },
|
||||||
|
{ count: selectedKeys.length }
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<Input
|
<Input
|
||||||
prefix={
|
prefix={
|
||||||
@@ -172,6 +181,7 @@ const SelectPanel: React.FC<SelectPanelProps> = ({
|
|||||||
}
|
}
|
||||||
size="small"
|
size="small"
|
||||||
allowClear
|
allowClear
|
||||||
|
status={'null' as any}
|
||||||
placeholder={searchPlaceholder}
|
placeholder={searchPlaceholder}
|
||||||
style={{
|
style={{
|
||||||
width: 300,
|
width: 300,
|
||||||
@@ -192,7 +202,7 @@ const SelectPanel: React.FC<SelectPanelProps> = ({
|
|||||||
) : (
|
) : (
|
||||||
<Empty
|
<Empty
|
||||||
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
||||||
description="No models found"
|
description={notFoundContent}
|
||||||
></Empty>
|
></Empty>
|
||||||
)}
|
)}
|
||||||
</Left>
|
</Left>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { MoreOutlined } from '@ant-design/icons';
|
import { MoreOutlined } from '@ant-design/icons';
|
||||||
|
import { useIntl } from '@umijs/max';
|
||||||
import { Transfer, TransferProps } from 'antd';
|
import { Transfer, TransferProps } from 'antd';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
@@ -72,6 +73,8 @@ interface TransferInnerProps extends TransferProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const TransferInner: React.FC<TransferInnerProps> = (props) => {
|
const TransferInner: React.FC<TransferInnerProps> = (props) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
const renderAllLabels = (info: {
|
const renderAllLabels = (info: {
|
||||||
selectedCount: number;
|
selectedCount: number;
|
||||||
totalCount: number;
|
totalCount: number;
|
||||||
@@ -79,7 +82,10 @@ const TransferInner: React.FC<TransferInnerProps> = (props) => {
|
|||||||
if (info.selectedCount) {
|
if (info.selectedCount) {
|
||||||
return (
|
return (
|
||||||
<span style={{ color: 'var(--ant-color-text-secondary)' }}>
|
<span style={{ color: 'var(--ant-color-text-secondary)' }}>
|
||||||
{info.selectedCount} selected
|
{intl.formatMessage(
|
||||||
|
{ id: 'common.select.count' },
|
||||||
|
{ count: info.selectedCount }
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import { PageAction } from '@/config';
|
import { PageAction } from '@/config';
|
||||||
import { PageActionType } from '@/config/types';
|
import { PageActionType } from '@/config/types';
|
||||||
|
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 { queryModelsList } from '@/pages/llmodels/apis';
|
||||||
|
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';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
@@ -18,6 +20,8 @@ const AllowModelsForm: React.FC<{
|
|||||||
currentData?: Partial<ListItem> | null;
|
currentData?: Partial<ListItem> | null;
|
||||||
action: PageActionType;
|
action: PageActionType;
|
||||||
}> = ({ currentData, action }) => {
|
}> = ({ currentData, action }) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const { getRuleMessage } = useAppUtils();
|
||||||
const form = Form.useFormInstance();
|
const form = Form.useFormInstance();
|
||||||
const allowedModelNames = Form.useWatch(
|
const allowedModelNames = Form.useWatch(
|
||||||
'allowed_model_names',
|
'allowed_model_names',
|
||||||
@@ -57,7 +61,7 @@ const AllowModelsForm: React.FC<{
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Divider></Divider>
|
<Divider></Divider>
|
||||||
<Label>Model Access</Label>
|
<Label>{intl.formatMessage({ id: 'apikeys.table.bindModels' })}</Label>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="allowed_type"
|
name="allowed_type"
|
||||||
initialValue="all"
|
initialValue="all"
|
||||||
@@ -65,17 +69,38 @@ const AllowModelsForm: React.FC<{
|
|||||||
>
|
>
|
||||||
<Radio.Group
|
<Radio.Group
|
||||||
options={[
|
options={[
|
||||||
{ label: 'All models', value: 'all' },
|
{
|
||||||
{ label: 'Selected models', value: 'custom' }
|
label: intl.formatMessage({ id: 'apikeys.models.all' }),
|
||||||
|
value: 'all'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: intl.formatMessage({ id: 'apikeys.models.selected' }),
|
||||||
|
value: 'custom'
|
||||||
|
}
|
||||||
]}
|
]}
|
||||||
></Radio.Group>
|
></Radio.Group>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="allowed_model_names" hidden={allowedType === 'all'}>
|
<Form.Item
|
||||||
|
name="allowed_model_names"
|
||||||
|
hidden={allowedType === 'all'}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: allowedType === 'custom',
|
||||||
|
message: getRuleMessage(
|
||||||
|
'select',
|
||||||
|
intl.formatMessage({ id: 'models.table.models' })
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
>
|
||||||
<SelectPanel
|
<SelectPanel
|
||||||
height={300}
|
height={300}
|
||||||
searchPlaceholder="Search by model name"
|
searchPlaceholder={intl.formatMessage({ id: 'common.filter.name' })}
|
||||||
options={modelList}
|
options={modelList}
|
||||||
selectedKeys={allowedModelNames || []}
|
selectedKeys={allowedModelNames || []}
|
||||||
|
notFoundContent={intl.formatMessage({
|
||||||
|
id: 'apikeys.models.noModelsFound'
|
||||||
|
})}
|
||||||
onSelectChange={(selectedKeys) => {
|
onSelectChange={(selectedKeys) => {
|
||||||
form.setFieldsValue({ allowed_model_names: selectedKeys });
|
form.setFieldsValue({ allowed_model_names: selectedKeys });
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -68,7 +68,11 @@ const useModelsColumns = ({
|
|||||||
showTitle: false
|
showTitle: false
|
||||||
},
|
},
|
||||||
render: (text: string[], record: ListItem) => (
|
render: (text: string[], record: ListItem) => (
|
||||||
<AutoTooltip ghost>{text?.join(', ')}</AutoTooltip>
|
<AutoTooltip ghost>
|
||||||
|
{text?.length
|
||||||
|
? text?.join(', ')
|
||||||
|
: intl.formatMessage({ id: 'common.select.option' })}
|
||||||
|
</AutoTooltip>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import TransferInner from '@/pages/_components/transfer';
|
import TransferInner from '@/pages/_components/transfer';
|
||||||
import { queryUsersList } from '@/pages/users/apis';
|
import { queryUsersList } from '@/pages/users/apis';
|
||||||
|
import { useIntl } from '@umijs/max';
|
||||||
import { Empty, Form, Radio } from 'antd';
|
import { Empty, Form, Radio } from 'antd';
|
||||||
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react';
|
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
@@ -22,6 +23,7 @@ interface AccessControlFormProps {
|
|||||||
|
|
||||||
const AccessControlForm = forwardRef((props: AccessControlFormProps, ref) => {
|
const AccessControlForm = forwardRef((props: AccessControlFormProps, ref) => {
|
||||||
const { currentData, onFinish } = props;
|
const { currentData, onFinish } = props;
|
||||||
|
const intl = useIntl();
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const setPublic = Form.useWatch('set_public', form);
|
const setPublic = Form.useWatch('set_public', form);
|
||||||
const [targetKeys, setTargetKeys] = useState<TransferKey[]>([]);
|
const [targetKeys, setTargetKeys] = useState<TransferKey[]>([]);
|
||||||
@@ -42,7 +44,6 @@ const AccessControlForm = forwardRef((props: AccessControlFormProps, ref) => {
|
|||||||
key: item.id,
|
key: item.id,
|
||||||
is_admin: item.is_admin
|
is_admin: item.is_admin
|
||||||
}));
|
}));
|
||||||
console.log('options', options);
|
|
||||||
setTotalPages(res.pagination.totalPage);
|
setTotalPages(res.pagination.totalPage);
|
||||||
setUserList(options);
|
setUserList(options);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -56,7 +57,6 @@ const AccessControlForm = forwardRef((props: AccessControlFormProps, ref) => {
|
|||||||
removeKeys: TransferKey[]
|
removeKeys: TransferKey[]
|
||||||
) => {
|
) => {
|
||||||
setTargetKeys(nextTargetKeys);
|
setTargetKeys(nextTargetKeys);
|
||||||
console.log('nextTargetKeys', nextTargetKeys);
|
|
||||||
const users = nextTargetKeys.map((key) => ({ id: key }));
|
const users = nextTargetKeys.map((key) => ({ id: key }));
|
||||||
form.setFieldsValue({ users });
|
form.setFieldsValue({ users });
|
||||||
};
|
};
|
||||||
@@ -108,41 +108,62 @@ const AccessControlForm = forwardRef((props: AccessControlFormProps, ref) => {
|
|||||||
set_public: true
|
set_public: true
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Label>Access Scope</Label>
|
<Label>{intl.formatMessage({ id: 'models.table.accessScope' })}</Label>
|
||||||
<Form.Item<AccessControlFormData> name="set_public" noStyle>
|
<Form.Item<AccessControlFormData> name="set_public" noStyle>
|
||||||
<Radio.Group
|
<Radio.Group
|
||||||
style={{ marginBottom: 12 }}
|
style={{ marginBottom: 12 }}
|
||||||
options={[
|
options={[
|
||||||
{ label: 'All users', value: true },
|
{
|
||||||
{ label: 'Selected users', value: false }
|
label: intl.formatMessage({ id: 'models.table.accessScope.all' }),
|
||||||
|
value: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: intl.formatMessage({
|
||||||
|
id: 'models.table.accessScope.selected'
|
||||||
|
}),
|
||||||
|
value: false
|
||||||
|
}
|
||||||
]}
|
]}
|
||||||
></Radio.Group>
|
></Radio.Group>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{!setPublic && (
|
{!setPublic && (
|
||||||
<>
|
<>
|
||||||
<Label>User Selection</Label>
|
<Label>
|
||||||
|
{intl.formatMessage({ id: 'models.table.userSelection' })}
|
||||||
|
</Label>
|
||||||
<Form.Item<AccessControlFormData> name="users">
|
<Form.Item<AccessControlFormData> name="users">
|
||||||
<TransferInner
|
<TransferInner
|
||||||
dataSource={userList}
|
dataSource={userList}
|
||||||
targetKeys={targetKeys}
|
targetKeys={targetKeys}
|
||||||
pagination={false}
|
pagination={false}
|
||||||
titles={['All Users', 'Selected Users']}
|
titles={[
|
||||||
|
intl.formatMessage({ id: 'models.table.users.all' }),
|
||||||
|
intl.formatMessage({
|
||||||
|
id: 'models.table.users.selected'
|
||||||
|
})
|
||||||
|
]}
|
||||||
locale={{
|
locale={{
|
||||||
notFoundContent: [
|
notFoundContent: [
|
||||||
<Empty
|
<Empty
|
||||||
key="all"
|
key="all"
|
||||||
description="No users found"
|
description={intl.formatMessage({
|
||||||
|
id: 'models.table.nouserFound'
|
||||||
|
})}
|
||||||
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
||||||
/>,
|
/>,
|
||||||
<Empty
|
<Empty
|
||||||
key="selected"
|
key="selected"
|
||||||
description="No users selected"
|
description={intl.formatMessage({
|
||||||
|
id: 'models.table.noselected'
|
||||||
|
})}
|
||||||
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
||||||
/>
|
/>
|
||||||
]
|
]
|
||||||
}}
|
}}
|
||||||
showSearch={{
|
showSearch={{
|
||||||
placeholder: 'Filter by username'
|
placeholder: intl.formatMessage({
|
||||||
|
id: 'common.filter.name'
|
||||||
|
})
|
||||||
}}
|
}}
|
||||||
filterOption={(inputValue, item) =>
|
filterOption={(inputValue, item) =>
|
||||||
item.title.toLowerCase().includes(inputValue.toLowerCase())
|
item.title.toLowerCase().includes(inputValue.toLowerCase())
|
||||||
@@ -151,7 +172,9 @@ const AccessControlForm = forwardRef((props: AccessControlFormProps, ref) => {
|
|||||||
<span className="flex-center gap-8">
|
<span className="flex-center gap-8">
|
||||||
<span>{item.title}</span>
|
<span>{item.title}</span>
|
||||||
<span className="text-tertiary">
|
<span className="text-tertiary">
|
||||||
{item.is_admin ? '(Admin)' : ''}
|
{item.is_admin
|
||||||
|
? `(${intl.formatMessage({ id: 'models.table.admin' })})`
|
||||||
|
: ''}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -467,7 +467,7 @@ const Models: React.FC<ModelsProps> = ({
|
|||||||
|
|
||||||
if (val === 'accessControl') {
|
if (val === 'accessControl') {
|
||||||
setOpenAccessControlModal({
|
setOpenAccessControlModal({
|
||||||
title: 'Access Settings',
|
title: intl.formatMessage({ id: 'models.button.accessSettings' }),
|
||||||
action: PageAction.EDIT,
|
action: PageAction.EDIT,
|
||||||
currentData: row,
|
currentData: row,
|
||||||
open: true
|
open: true
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export const ActionList: ActionItem[] = [
|
|||||||
icon: icons.ApiOutlined
|
icon: icons.ApiOutlined
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Access Settings',
|
label: 'models.button.accessSettings',
|
||||||
key: 'accessControl',
|
key: 'accessControl',
|
||||||
icon: icons.Private
|
icon: icons.Private
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user