fix: refresh enable backend state
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
import { atom } from 'jotai';
|
||||||
|
|
||||||
|
export const enabledBackendsAtom = atom<any>(null);
|
||||||
@@ -430,6 +430,7 @@ export default function useTableFetch<T>(
|
|||||||
extraStatus,
|
extraStatus,
|
||||||
TABLE_SORT_DIRECTIONS,
|
TABLE_SORT_DIRECTIONS,
|
||||||
debounceFetchData,
|
debounceFetchData,
|
||||||
|
setDataSource,
|
||||||
setQueryParams,
|
setQueryParams,
|
||||||
handleDelete,
|
handleDelete,
|
||||||
handleDeleteBatch,
|
handleDeleteBatch,
|
||||||
|
|||||||
@@ -44,5 +44,5 @@ export default {
|
|||||||
'backend.filter.source': 'Filter by source',
|
'backend.filter.source': 'Filter by source',
|
||||||
'backend.add.custom': 'Custom',
|
'backend.add.custom': 'Custom',
|
||||||
'backend.add.community': 'Community Backends',
|
'backend.add.community': 'Community Backends',
|
||||||
'backend.community.title': 'Community Backends Marketplace'
|
'backend.community.title': 'Community Backend Marketplace'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ export default {
|
|||||||
'clusters.table.ip.internal': 'Internal',
|
'clusters.table.ip.internal': 'Internal',
|
||||||
'clusters.table.ip.external': 'External',
|
'clusters.table.ip.external': 'External',
|
||||||
'clusters.form.serverUrl.tips':
|
'clusters.form.serverUrl.tips':
|
||||||
'Specify an externally accessible GPUStack service URL if the worker cannot access GPUStack directly.',
|
'Specify an externally accessible GPUStack service URL if the worker cannot access GPUStack Server directly.',
|
||||||
'clusters.form.setDefault': 'Set as Default',
|
'clusters.form.setDefault': 'Set as Default',
|
||||||
'clusters.form.setDefault.tips': 'Default for deployment.',
|
'clusters.form.setDefault.tips': 'Default for deployment.',
|
||||||
'clusters.addworker.noClusters': 'No available Docker clusters found',
|
'clusters.addworker.noClusters': 'No available Docker clusters found',
|
||||||
|
|||||||
@@ -39,5 +39,5 @@ export default {
|
|||||||
'users.status.deactivate': 'Deactivate Account',
|
'users.status.deactivate': 'Deactivate Account',
|
||||||
'users.status.inactiveAccount': 'Inactive Account',
|
'users.status.inactiveAccount': 'Inactive Account',
|
||||||
'users.login.getInitialPassword':
|
'users.login.getInitialPassword':
|
||||||
'Run the following command on your server to retrieve the initial admin password.'
|
'Run the following command on your GPUStack Server to retrieve the initial admin password.'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -44,5 +44,5 @@ export default {
|
|||||||
'backend.filter.source': 'Filter by source',
|
'backend.filter.source': 'Filter by source',
|
||||||
'backend.add.custom': 'Custom',
|
'backend.add.custom': 'Custom',
|
||||||
'backend.add.community': 'Community Backends',
|
'backend.add.community': 'Community Backends',
|
||||||
'backend.community.title': 'Community Backends Marketplace'
|
'backend.community.title': 'Community Backend Marketplace'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ export default {
|
|||||||
'clusters.table.ip.internal': 'Internal',
|
'clusters.table.ip.internal': 'Internal',
|
||||||
'clusters.table.ip.external': 'External',
|
'clusters.table.ip.external': 'External',
|
||||||
'clusters.form.serverUrl.tips':
|
'clusters.form.serverUrl.tips':
|
||||||
'Specify an externally accessible GPUStack service URL if the worker cannot access GPUStack directly.',
|
'Specify an externally accessible GPUStack service URL if the worker cannot access GPUStack Server directly.',
|
||||||
'clusters.form.setDefault': 'Set as Default',
|
'clusters.form.setDefault': 'Set as Default',
|
||||||
'clusters.form.setDefault.tips': 'Default for deployment.',
|
'clusters.form.setDefault.tips': 'Default for deployment.',
|
||||||
'clusters.addworker.noClusters': 'No available Docker clusters found',
|
'clusters.addworker.noClusters': 'No available Docker clusters found',
|
||||||
@@ -217,7 +217,7 @@ export default {
|
|||||||
// 78. 'clusters.addworker.dataVolume.tips': 'Specify a data storage path for GPUStack.',
|
// 78. 'clusters.addworker.dataVolume.tips': 'Specify a data storage path for GPUStack.',
|
||||||
// 79. 'clusters.table.ip.internal': 'Internal',
|
// 79. 'clusters.table.ip.internal': 'Internal',
|
||||||
// 80. 'clusters.table.ip.external': 'External',
|
// 80. 'clusters.table.ip.external': 'External',
|
||||||
// 81. 'clusters.form.serverUrl.tips': 'Specify an externally accessible GPUStack service URL if the worker cannot access GPUStack directly.',
|
// 81. 'clusters.form.serverUrl.tips': 'Specify an externally accessible GPUStack service URL if the worker cannot access GPUStack Server directly.',
|
||||||
// 82. 'clusters.addworker.externalIP.tips': 'Specify an external IP if the worker is in a VPC or private network.',
|
// 82. 'clusters.addworker.externalIP.tips': 'Specify an external IP if the worker is in a VPC or private network.',
|
||||||
// 83. 'clusters.form.setDefault': 'Set as Default',
|
// 83. 'clusters.form.setDefault': 'Set as Default',
|
||||||
// 84. 'clusters.form.setDefault.tips': 'Default for deployment',
|
// 84. 'clusters.form.setDefault.tips': 'Default for deployment',
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export default {
|
|||||||
'users.status.deactivate': 'Deactivate Account',
|
'users.status.deactivate': 'Deactivate Account',
|
||||||
'users.status.inactiveAccount': 'Inactive Account',
|
'users.status.inactiveAccount': 'Inactive Account',
|
||||||
'users.login.getInitialPassword':
|
'users.login.getInitialPassword':
|
||||||
'Run the following command on your server to retrieve the initial admin password.'
|
'Run the following command on your GPUStack Server to retrieve the initial admin password.'
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
@@ -48,5 +48,5 @@ export default {
|
|||||||
// 2. 'users.status.activate': 'Activate Account',
|
// 2. 'users.status.activate': 'Activate Account',
|
||||||
// 3. 'users.status.deactivate': 'Deactivate Account',
|
// 3. 'users.status.deactivate': 'Deactivate Account',
|
||||||
// 4. 'users.status.inactiveAccount': 'Inactive Account',
|
// 4. 'users.status.inactiveAccount': 'Inactive Account',
|
||||||
// 5. 'users.login.getInitialPassword': 'Run the following command on your server to retrieve the initial admin password.'
|
// 5. 'users.login.getInitialPassword': 'Run the following command on your GPUStack Server to retrieve the initial admin password.'
|
||||||
// ========== End of To-Do List ==========
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export default {
|
|||||||
'backend.filter.source': 'Filter by source',
|
'backend.filter.source': 'Filter by source',
|
||||||
'backend.add.custom': 'Custom',
|
'backend.add.custom': 'Custom',
|
||||||
'backend.add.community': 'Community Backends',
|
'backend.add.community': 'Community Backends',
|
||||||
'backend.community.title': 'Community Backends Marketplace'
|
'backend.community.title': 'Community Backend Marketplace'
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
@@ -53,5 +53,5 @@ export default {
|
|||||||
// 3. 'backend.filter.source': 'Filter by source',
|
// 3. 'backend.filter.source': 'Filter by source',
|
||||||
// 4. 'backend.add.custom': 'Custom',
|
// 4. 'backend.add.custom': 'Custom',
|
||||||
// 5. 'backend.add.community': 'Community Backends',
|
// 5. 'backend.add.community': 'Community Backends',
|
||||||
// 6. 'backend.community.title': 'Community Backends Marketplace'
|
// 6. 'backend.community.title': 'Community Backend Marketplace'
|
||||||
// ========== End of To-Do List ==========
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ export default {
|
|||||||
'clusters.table.ip.internal': 'Внутренний',
|
'clusters.table.ip.internal': 'Внутренний',
|
||||||
'clusters.table.ip.external': 'Внешний',
|
'clusters.table.ip.external': 'Внешний',
|
||||||
'clusters.form.serverUrl.tips':
|
'clusters.form.serverUrl.tips':
|
||||||
'Если рабочий узел не может напрямую получить доступ к GPUStack, укажите внешний URL службы GPUStack.',
|
'Если рабочий узел не может напрямую получить доступ к GPUStack Server, укажите внешний URL службы GPUStack Server.',
|
||||||
'clusters.form.setDefault': 'Установить по умолчанию',
|
'clusters.form.setDefault': 'Установить по умолчанию',
|
||||||
'clusters.form.setDefault.tips':
|
'clusters.form.setDefault.tips':
|
||||||
'Использовать по умолчанию для развертывания.',
|
'Использовать по умолчанию для развертывания.',
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ export default {
|
|||||||
'已将 {count} 个新节点添加到集群中。',
|
'已将 {count} 个新节点添加到集群中。',
|
||||||
'clusters.addworker.message.success_multiple':
|
'clusters.addworker.message.success_multiple':
|
||||||
'已将 {count} 个新节点添加到集群中。',
|
'已将 {count} 个新节点添加到集群中。',
|
||||||
'clusters.create.serverUrl': 'GPUStack 服务地址',
|
'clusters.create.serverUrl': 'GPUStack Server 节点地址',
|
||||||
'clusters.create.workerConfig': '节点配置',
|
'clusters.create.workerConfig': '节点配置',
|
||||||
'clusters.addworker.containerName': '节点容器名称',
|
'clusters.addworker.containerName': '节点容器名称',
|
||||||
'clusters.addworker.containerName.tips': '为节点容器指定一个名称。',
|
'clusters.addworker.containerName.tips': '为节点容器指定一个名称。',
|
||||||
@@ -111,7 +111,7 @@ export default {
|
|||||||
'clusters.table.ip.internal': '内',
|
'clusters.table.ip.internal': '内',
|
||||||
'clusters.table.ip.external': '外',
|
'clusters.table.ip.external': '外',
|
||||||
'clusters.form.serverUrl.tips':
|
'clusters.form.serverUrl.tips':
|
||||||
'如果节点无法直接访问 GPUStack,则指定一个可访问的外部 GPUStack 服务地址。',
|
'如果节点无法直接访问 GPUStack Server,则指定一个可访问的外部 GPUStack Server 地址。',
|
||||||
'clusters.form.setDefault': '设为默认',
|
'clusters.form.setDefault': '设为默认',
|
||||||
'clusters.form.setDefault.tips': '部署时的默认集群。',
|
'clusters.form.setDefault.tips': '部署时的默认集群。',
|
||||||
'clusters.addworker.noClusters': '无可用的 Docker 集群',
|
'clusters.addworker.noClusters': '无可用的 Docker 集群',
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ export default {
|
|||||||
'models.form.backendVersions.tips': `如需使用更多版本,请前往{link}页面并编辑对应的后端以添加版本。`,
|
'models.form.backendVersions.tips': `如需使用更多版本,请前往{link}页面并编辑对应的后端以添加版本。`,
|
||||||
'models.catalog.nogpus.tips': '所选集群中没有兼容该模型的 GPU。',
|
'models.catalog.nogpus.tips': '所选集群中没有兼容该模型的 GPU。',
|
||||||
'models.form.modelfile.notfound':
|
'models.form.modelfile.notfound':
|
||||||
'你指定的模型文件路径在 GPUStack 服务器上不存在。建议在 GPUStack 服务器和 GPUStack 节点上使用相同的模型文件路径,这有助于 GPUStack 做出更优的调度与决策。',
|
'你指定的模型文件路径在 GPUStack Server 节点上不存在。建议在 GPUStack Server 节点和 GPUStack 节点上使用相同的模型文件路径,这有助于 GPUStack 做出更优的调度与决策。',
|
||||||
'models.form.readyWorkers': '节点就绪',
|
'models.form.readyWorkers': '节点就绪',
|
||||||
'models.form.maxContextLength': '最大上下文长度',
|
'models.form.maxContextLength': '最大上下文长度',
|
||||||
'models.form.backend.helperText': '该社区后端暂未启用,部署后将自动启用',
|
'models.form.backend.helperText': '该社区后端暂未启用,部署后将自动启用',
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
|
import { enabledBackendsAtom } from '@/atoms/backend';
|
||||||
import GSDrawer from '@/components/scroller-modal/gs-drawer';
|
import GSDrawer from '@/components/scroller-modal/gs-drawer';
|
||||||
import ColumnWrapper from '@/pages/_components/column-wrapper';
|
import ColumnWrapper from '@/pages/_components/column-wrapper';
|
||||||
import Separator from '@/pages/llmodels/components/separator';
|
import Separator from '@/pages/llmodels/components/separator';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
import React from 'react';
|
import { useAtom } from 'jotai';
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { ListItem } from '../config/types';
|
import { ListItem } from '../config/types';
|
||||||
import useEnableBackend from '../services/use-enable-backend';
|
import useEnableBackend from '../services/use-enable-backend';
|
||||||
@@ -23,6 +25,7 @@ const AddCommunityModal: React.FC<{
|
|||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const { handleEnableBackend } = useEnableBackend();
|
const { handleEnableBackend } = useEnableBackend();
|
||||||
const [currentData, setCurrentData] = React.useState<any>(null);
|
const [currentData, setCurrentData] = React.useState<any>(null);
|
||||||
|
const [, setEnabledBackendAtom] = useAtom(enabledBackendsAtom);
|
||||||
|
|
||||||
const handleOnEnable = async (checked: boolean, data: ListItem) => {
|
const handleOnEnable = async (checked: boolean, data: ListItem) => {
|
||||||
await handleEnableBackend({
|
await handleEnableBackend({
|
||||||
@@ -32,12 +35,23 @@ const AddCommunityModal: React.FC<{
|
|||||||
enabled: checked
|
enabled: checked
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
setEnabledBackendAtom({
|
||||||
|
...data,
|
||||||
|
enabled: checked
|
||||||
|
});
|
||||||
onRefresh?.();
|
onRefresh?.();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOnClick = (data: ListItem) => {
|
const handleOnClick = (data: ListItem) => {
|
||||||
setCurrentData(data);
|
setCurrentData(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!open) {
|
||||||
|
setEnabledBackendAtom(null);
|
||||||
|
}
|
||||||
|
}, [open]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GSDrawer
|
<GSDrawer
|
||||||
open={open}
|
open={open}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
|
import { enabledBackendsAtom } from '@/atoms/backend';
|
||||||
import IconFont from '@/components/icon-font';
|
import IconFont from '@/components/icon-font';
|
||||||
import ThemeTag from '@/components/tags-wrapper/theme-tag';
|
import ThemeTag from '@/components/tags-wrapper/theme-tag';
|
||||||
import useTableFetch from '@/hooks/use-table-fetch';
|
import useTableFetch from '@/hooks/use-table-fetch';
|
||||||
import { SearchOutlined } from '@ant-design/icons';
|
import { SearchOutlined } from '@ant-design/icons';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
import { Input, Tooltip } from 'antd';
|
import { Input, Tooltip } from 'antd';
|
||||||
|
import { useAtom } from 'jotai';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
@@ -28,19 +30,46 @@ const CommunityBackends: React.FC<{
|
|||||||
onClick: (data: ListItem) => void;
|
onClick: (data: ListItem) => void;
|
||||||
}> = ({ onEnable, onClick }) => {
|
}> = ({ onEnable, onClick }) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const [enabledBackendAtom] = useAtom(enabledBackendsAtom);
|
||||||
const [currentData, setCurrentData] = React.useState<ListItem | null>(null);
|
const [currentData, setCurrentData] = React.useState<ListItem | null>(null);
|
||||||
const { dataSource, loadMore, queryParams, handleSearch, handleNameChange } =
|
const {
|
||||||
useTableFetch<ListItem>({
|
dataSource,
|
||||||
fetchAPI: queryBackendsList,
|
loadMore,
|
||||||
API: INFERENCE_BACKEND_API,
|
queryParams,
|
||||||
watch: false,
|
handleSearch,
|
||||||
isInfiniteScroll: true,
|
setDataSource,
|
||||||
contentForDelete: 'backends.title',
|
handleNameChange
|
||||||
defaultQueryParams: {
|
} = useTableFetch<ListItem>({
|
||||||
perPage: 24,
|
fetchAPI: queryBackendsList,
|
||||||
community: 1
|
API: INFERENCE_BACKEND_API,
|
||||||
}
|
watch: false,
|
||||||
});
|
isInfiniteScroll: true,
|
||||||
|
contentForDelete: 'backends.title',
|
||||||
|
defaultQueryParams: {
|
||||||
|
perPage: 24,
|
||||||
|
community: 1
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (enabledBackendAtom) {
|
||||||
|
setDataSource((prev) => {
|
||||||
|
const newDataList = prev.dataList.map((item) => {
|
||||||
|
if (item.id === enabledBackendAtom.id) {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
enabled: enabledBackendAtom.enabled
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
dataList: newDataList
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [enabledBackendAtom]);
|
||||||
|
|
||||||
const handleOnClickItem = (data: ListItem) => {
|
const handleOnClickItem = (data: ListItem) => {
|
||||||
onClick(data);
|
onClick(data);
|
||||||
|
|||||||
Reference in New Issue
Block a user