feat: duplicate deployment
This commit is contained in:
@@ -27,7 +27,12 @@ import _ from 'lodash';
|
||||
import React, { useCallback, useEffect, useMemo } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { MODEL_INSTANCE_API } from '../apis';
|
||||
import { InstanceStatusMap, InstanceStatusMapValue, status } from '../config';
|
||||
import {
|
||||
InstanceStatusMap,
|
||||
InstanceStatusMapValue,
|
||||
modelCategoriesMap,
|
||||
status
|
||||
} from '../config';
|
||||
import { backendOptionsMap } from '../config/backend-parameters';
|
||||
import { generateSource } from '../config/button-actions';
|
||||
import {
|
||||
@@ -431,12 +436,18 @@ const InstanceItem: React.FC<InstanceItemProps> = ({
|
||||
const intl = useIntl();
|
||||
const actionItems = useMemo(() => {
|
||||
return _.filter(childActionList, (action: any) => {
|
||||
if (action.key === 'benchmark') {
|
||||
return (
|
||||
action.status.includes(instanceData.state) &&
|
||||
modelData?.categories?.includes(modelCategoriesMap.llm)
|
||||
);
|
||||
}
|
||||
if (action.status && action.status.length > 0) {
|
||||
return action.status.includes(instanceData.state);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}, [instanceData.state]);
|
||||
}, [instanceData.state, modelData]);
|
||||
|
||||
const createFileName = (name: string) => {
|
||||
const timestamp = dayjs().format('YYYY-MM-DD_HH-mm-ss');
|
||||
|
||||
@@ -15,6 +15,9 @@ import useExpandedRowKeys from '@/hooks/use-expanded-row-keys';
|
||||
import useTableRowSelection from '@/hooks/use-table-row-selection';
|
||||
import PageBox from '@/pages/_components/page-box';
|
||||
import useNoResourceResult from '@/pages/llmodels/hooks/use-no-resource-result';
|
||||
import { TargetStatusValueMap } from '@/pages/model-routes/config';
|
||||
import useOpenPlayground from '@/pages/model-routes/hooks/use-open-playground';
|
||||
import useQueryTargets from '@/pages/model-routes/services/use-query-targets';
|
||||
import { handleBatchRequest } from '@/utils';
|
||||
import { DownOutlined, SearchOutlined, SyncOutlined } from '@ant-design/icons';
|
||||
import { useIntl, useNavigate, useSearchParams } from '@umijs/max';
|
||||
@@ -54,11 +57,10 @@ import {
|
||||
ModelInstanceListItem,
|
||||
SourceType
|
||||
} from '../config/types';
|
||||
import useEditDeployment from '../hooks/use-edit-deployment';
|
||||
import useFilterStatus from '../hooks/use-filter-status';
|
||||
import useFormInitialValues from '../hooks/use-form-initial-values';
|
||||
import useModelsColumns from '../hooks/use-models-columns';
|
||||
import AccessControlModal from './access-control-modal';
|
||||
import APIAccessInfoModal from './api-access-info';
|
||||
import DeployModal from './deploy-modal';
|
||||
import Instances from './instances';
|
||||
import UpdateModelModal from './update-modal';
|
||||
@@ -140,13 +142,12 @@ const Models: React.FC<ModelsProps> = ({
|
||||
const [searchParams] = useSearchParams();
|
||||
const page = searchParams.get('page');
|
||||
const { saveScrollHeight, restoreScrollHeight } = useBodyScroll();
|
||||
const [updateFormInitials, setUpdateFormInitials] = useState<{
|
||||
data: any;
|
||||
isGGUF: boolean;
|
||||
}>({
|
||||
data: {},
|
||||
isGGUF: false
|
||||
});
|
||||
const {
|
||||
openEditModalStatus,
|
||||
openEditModal,
|
||||
openDuplicateModal,
|
||||
closeEditModal
|
||||
} = useEditDeployment();
|
||||
const [expandAtom, setExpandAtom] = useAtom(modelsExpandKeysAtom);
|
||||
const [modelsSession, setModelsSession] = useAtom(modelsSessionAtom);
|
||||
const intl = useIntl();
|
||||
@@ -159,17 +160,18 @@ const Models: React.FC<ModelsProps> = ({
|
||||
removeExpandedRowKey,
|
||||
expandedRowKeys
|
||||
} = useExpandedRowKeys(expandAtom);
|
||||
const { handleOpenPlayGround } = useOpenPlayground();
|
||||
const { labelRender, optionRender, handleStatusChange, statusOptions } =
|
||||
useFilterStatus({
|
||||
onStatusChange: onStatusChange
|
||||
});
|
||||
const { fetchData: fetchTargets, dataList: targetList } = useQueryTargets();
|
||||
|
||||
useEffect(() => {
|
||||
fetchTargets({});
|
||||
}, []);
|
||||
|
||||
const [apiAccessInfo, setAPIAccessInfo] = useState<any>({
|
||||
show: false,
|
||||
data: {}
|
||||
});
|
||||
const [openLogModal, setOpenLogModal] = useState(false);
|
||||
const [openAddModal, setOpenAddModal] = useState(false);
|
||||
const [openDeployModal, setOpenDeployModal] = useState<{
|
||||
show: boolean;
|
||||
width: number | string;
|
||||
@@ -183,7 +185,6 @@ const Models: React.FC<ModelsProps> = ({
|
||||
isGGUF: false,
|
||||
source: modelSourceMap.huggingface_value as SourceType
|
||||
});
|
||||
const currentData = useRef<ListItem>({} as ListItem);
|
||||
const [currentInstance, setCurrentInstance] = useState<{
|
||||
url: string;
|
||||
status: string;
|
||||
@@ -194,17 +195,6 @@ const Models: React.FC<ModelsProps> = ({
|
||||
url: '',
|
||||
status: ''
|
||||
});
|
||||
const [openAccessControlModal, setOpenAccessControlModal] = useState<{
|
||||
open: boolean;
|
||||
currentData: ListItem | null;
|
||||
title: string;
|
||||
action: PageActionType;
|
||||
}>({
|
||||
open: false,
|
||||
currentData: null,
|
||||
title: '',
|
||||
action: PageAction.CREATE
|
||||
});
|
||||
const modalRef = useRef<any>(null);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -223,10 +213,6 @@ const Models: React.FC<ModelsProps> = ({
|
||||
};
|
||||
}, []);
|
||||
|
||||
const setCurrentData = (data: ListItem) => {
|
||||
currentData.current = data;
|
||||
};
|
||||
|
||||
const handleOnSort = (order: TableOrder | Array<TableOrder>) => {
|
||||
onTableSort?.(order);
|
||||
};
|
||||
@@ -253,16 +239,29 @@ const Models: React.FC<ModelsProps> = ({
|
||||
};
|
||||
|
||||
const handleModalOk = async (data: FormData) => {
|
||||
const currentData = openEditModalStatus.currentData;
|
||||
try {
|
||||
await updateModel({
|
||||
data,
|
||||
id: currentData.current?.id as number
|
||||
});
|
||||
setOpenAddModal(false);
|
||||
message.success(intl.formatMessage({ id: 'common.message.success' }));
|
||||
if (data.replicas > currentData.current?.replicas) {
|
||||
updateExpandedRowKeys([currentData.current?.id, ...expandedRowKeys]);
|
||||
if (currentData.realAction === PageAction.COPY) {
|
||||
const modelData = await createModel({
|
||||
data
|
||||
});
|
||||
|
||||
if (data.replicas > 0) {
|
||||
updateExpandedRowKeys([modelData.id, ...expandedRowKeys]);
|
||||
}
|
||||
}
|
||||
if (currentData.realAction === PageAction.EDIT) {
|
||||
await updateModel({
|
||||
data,
|
||||
id: currentData.row.id as number
|
||||
});
|
||||
|
||||
if (data.replicas > currentData.row.replicas) {
|
||||
updateExpandedRowKeys([currentData.row.id, ...expandedRowKeys]);
|
||||
}
|
||||
}
|
||||
closeEditModal();
|
||||
message.success(intl.formatMessage({ id: 'common.message.success' }));
|
||||
setTimeout(() => {
|
||||
handleSearch();
|
||||
}, 150);
|
||||
@@ -271,7 +270,7 @@ const Models: React.FC<ModelsProps> = ({
|
||||
};
|
||||
|
||||
const handleModalCancel = useCallback(() => {
|
||||
setOpenAddModal(false);
|
||||
closeEditModal();
|
||||
restoreScrollHeight();
|
||||
}, []);
|
||||
|
||||
@@ -282,29 +281,28 @@ const Models: React.FC<ModelsProps> = ({
|
||||
});
|
||||
};
|
||||
|
||||
const handleCreateModel = useCallback(
|
||||
async (data: FormData) => {
|
||||
try {
|
||||
console.log('data:', data, openDeployModal);
|
||||
const refreshListStatus = (modelData: ListItem) => {
|
||||
setTimeout(() => {
|
||||
updateExpandedRowKeys([modelData.id, ...expandedRowKeys]);
|
||||
}, 300);
|
||||
message.success(intl.formatMessage({ id: 'common.message.success' }));
|
||||
setTimeout(() => {
|
||||
handleSearch?.();
|
||||
}, 150);
|
||||
};
|
||||
|
||||
const modelData = await createModel({
|
||||
data
|
||||
});
|
||||
setOpenDeployModal({
|
||||
...openDeployModal,
|
||||
show: false
|
||||
});
|
||||
setTimeout(() => {
|
||||
updateExpandedRowKeys([modelData.id, ...expandedRowKeys]);
|
||||
}, 300);
|
||||
message.success(intl.formatMessage({ id: 'common.message.success' }));
|
||||
setTimeout(() => {
|
||||
handleSearch?.();
|
||||
}, 150);
|
||||
} catch (error) {}
|
||||
},
|
||||
[openDeployModal]
|
||||
);
|
||||
const handleCreateModel = async (data: FormData) => {
|
||||
try {
|
||||
const modelData = await createModel({
|
||||
data
|
||||
});
|
||||
setOpenDeployModal({
|
||||
...openDeployModal,
|
||||
show: false
|
||||
});
|
||||
refreshListStatus(modelData);
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
const handleLogModalCancel = useCallback(() => {
|
||||
setOpenLogModal(false);
|
||||
@@ -400,28 +398,23 @@ const Models: React.FC<ModelsProps> = ({
|
||||
return `${MODELS_API}/${params.id}/instances`;
|
||||
}, []);
|
||||
|
||||
const handleEdit = async (row: ListItem) => {
|
||||
const handleEdit = async (row: ListItem, realAction: PageActionType) => {
|
||||
const initialValues = generateFormValues(row, []);
|
||||
setUpdateFormInitials({
|
||||
data: initialValues,
|
||||
isGGUF: false
|
||||
});
|
||||
setCurrentData(row);
|
||||
setOpenAddModal(true);
|
||||
if (realAction === PageAction.EDIT) {
|
||||
openEditModal(initialValues, row);
|
||||
} else if (realAction === PageAction.COPY) {
|
||||
openDuplicateModal(initialValues, row);
|
||||
}
|
||||
saveScrollHeight();
|
||||
};
|
||||
|
||||
const handleViewAPIInfo = useCallback((row: ListItem) => {
|
||||
setAPIAccessInfo({
|
||||
show: true,
|
||||
data: row
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleSelect = useMemoizedFn(async (val: any, row: ListItem) => {
|
||||
try {
|
||||
if (val === 'edit') {
|
||||
handleEdit(row);
|
||||
handleEdit(row, PageAction.EDIT);
|
||||
}
|
||||
if (val === 'copy') {
|
||||
handleEdit(row, PageAction.COPY);
|
||||
}
|
||||
if (val === 'delete') {
|
||||
handleDelete(row);
|
||||
@@ -433,10 +426,6 @@ const Models: React.FC<ModelsProps> = ({
|
||||
onStart?.();
|
||||
}
|
||||
|
||||
if (val === 'api') {
|
||||
handleViewAPIInfo(row);
|
||||
}
|
||||
|
||||
if (val === 'stop') {
|
||||
modalRef.current?.show({
|
||||
content: 'models.instances',
|
||||
@@ -450,13 +439,16 @@ const Models: React.FC<ModelsProps> = ({
|
||||
}
|
||||
});
|
||||
}
|
||||
if (val === 'chat') {
|
||||
const targetRoute = targetList.find(
|
||||
(target) =>
|
||||
target.model_id === row.id &&
|
||||
target.state === TargetStatusValueMap.Active
|
||||
);
|
||||
|
||||
if (val === 'accessControl') {
|
||||
setOpenAccessControlModal({
|
||||
title: intl.formatMessage({ id: 'models.button.accessSettings' }),
|
||||
action: PageAction.EDIT,
|
||||
currentData: row,
|
||||
open: true
|
||||
handleOpenPlayGround({
|
||||
categories: row.categories || [],
|
||||
name: targetRoute?.route_name || ''
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -551,7 +543,8 @@ const Models: React.FC<ModelsProps> = ({
|
||||
return {
|
||||
handleSelect,
|
||||
clusterList,
|
||||
sortOrder
|
||||
sortOrder,
|
||||
targetList: targetList
|
||||
};
|
||||
}, [handleSelect, clusterList, sortOrder]);
|
||||
|
||||
@@ -565,14 +558,6 @@ const Models: React.FC<ModelsProps> = ({
|
||||
}
|
||||
});
|
||||
|
||||
const handleCancelAccessControl = () => {
|
||||
setOpenAccessControlModal({
|
||||
...openAccessControlModal,
|
||||
currentData: null,
|
||||
open: false
|
||||
});
|
||||
};
|
||||
|
||||
const { noResourceResult } = useNoResourceResult({
|
||||
loadend: loadend,
|
||||
loading: loading,
|
||||
@@ -735,10 +720,10 @@ const Models: React.FC<ModelsProps> = ({
|
||||
></SealTable>
|
||||
</PageBox>
|
||||
<UpdateModelModal
|
||||
open={openAddModal}
|
||||
action={PageAction.EDIT}
|
||||
title={intl.formatMessage({ id: 'models.title.edit' })}
|
||||
updateFormInitials={updateFormInitials}
|
||||
open={openEditModalStatus.open}
|
||||
action={openEditModalStatus.action}
|
||||
title={openEditModalStatus.title}
|
||||
currentData={openEditModalStatus.currentData}
|
||||
clusterList={clusterList}
|
||||
onCancel={handleModalCancel}
|
||||
onOk={handleModalOk}
|
||||
@@ -765,23 +750,6 @@ const Models: React.FC<ModelsProps> = ({
|
||||
onCancel={handleLogModalCancel}
|
||||
></ViewLogsModal>
|
||||
<DeleteModal ref={modalRef}></DeleteModal>
|
||||
<APIAccessInfoModal
|
||||
open={apiAccessInfo.show}
|
||||
data={apiAccessInfo.data}
|
||||
onClose={() => {
|
||||
setAPIAccessInfo({
|
||||
...apiAccessInfo,
|
||||
show: false
|
||||
});
|
||||
}}
|
||||
></APIAccessInfoModal>
|
||||
<AccessControlModal
|
||||
onCancel={handleCancelAccessControl}
|
||||
title={openAccessControlModal.title}
|
||||
open={openAccessControlModal.open}
|
||||
currentData={openAccessControlModal.currentData}
|
||||
action={openAccessControlModal.action}
|
||||
></AccessControlModal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import ModalFooter from '@/components/modal-footer';
|
||||
import GSDrawer from '@/components/scroller-modal/gs-drawer';
|
||||
import { PageAction } from '@/config';
|
||||
import { PageActionType } from '@/config/types';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Button } from 'antd';
|
||||
import _ from 'lodash';
|
||||
import React, { useEffect, useMemo, useRef } from 'react';
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import ColumnWrapper from '../../_components/column-wrapper';
|
||||
import {
|
||||
DeployFormKeyMap,
|
||||
@@ -22,9 +22,10 @@ type AddModalProps = {
|
||||
title: string;
|
||||
action: PageActionType;
|
||||
open: boolean;
|
||||
updateFormInitials: {
|
||||
currentData: {
|
||||
data: FormData;
|
||||
isGGUF: boolean;
|
||||
realAction?: PageActionType;
|
||||
};
|
||||
clusterList: Global.BaseOption<
|
||||
number,
|
||||
@@ -48,7 +49,7 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
||||
onOk,
|
||||
onCancel,
|
||||
clusterList,
|
||||
updateFormInitials: { isGGUF, data: formData }
|
||||
currentData: { isGGUF, data: formData, realAction }
|
||||
} = props || {};
|
||||
const intl = useIntl();
|
||||
const {
|
||||
@@ -198,14 +199,6 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
||||
onCancel?.();
|
||||
};
|
||||
|
||||
const showExtraButton = useMemo(() => {
|
||||
return (
|
||||
warningStatus.show &&
|
||||
warningStatus.type !== 'success' &&
|
||||
!warningStatus.isDefault
|
||||
);
|
||||
}, [warningStatus.show, warningStatus.type, warningStatus.isDefault]);
|
||||
|
||||
useEffect(() => {
|
||||
const initGPUSelector = async () => {
|
||||
const gpuOptions = await formRef.current?.getGPUOptionList({
|
||||
@@ -256,31 +249,23 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
||||
}}
|
||||
footer={
|
||||
<>
|
||||
<CompatibilityAlert
|
||||
showClose={false}
|
||||
onClose={() => {
|
||||
setWarningStatus({
|
||||
show: false,
|
||||
message: ''
|
||||
});
|
||||
}}
|
||||
warningStatus={warningStatus}
|
||||
contentStyle={{ paddingInline: 0 }}
|
||||
></CompatibilityAlert>
|
||||
{realAction === PageAction.EDIT && (
|
||||
<CompatibilityAlert
|
||||
showClose={false}
|
||||
onClose={() => {
|
||||
setWarningStatus({
|
||||
show: false,
|
||||
message: ''
|
||||
});
|
||||
}}
|
||||
warningStatus={warningStatus}
|
||||
contentStyle={{ paddingInline: 0 }}
|
||||
></CompatibilityAlert>
|
||||
)}
|
||||
<ModalFooter
|
||||
style={ModalFooterStyle}
|
||||
onCancel={onCancel}
|
||||
onOk={handleSumit}
|
||||
showOkBtn={!showExtraButton}
|
||||
extra={
|
||||
showExtraButton && (
|
||||
<Button type="primary" onClick={handleSubmitAnyway}>
|
||||
{intl.formatMessage({
|
||||
id: 'models.form.submit.anyway'
|
||||
})}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
></ModalFooter>
|
||||
</>
|
||||
}
|
||||
|
||||
@@ -39,16 +39,21 @@ export const ActionList: ActionItem[] = [
|
||||
key: 'edit',
|
||||
icon: icons.EditOutlined
|
||||
},
|
||||
{
|
||||
label: 'models.openinplayground',
|
||||
key: 'chat',
|
||||
icon: icons.ExperimentOutlined
|
||||
},
|
||||
{
|
||||
key: 'copy',
|
||||
label: 'common.button.duplicate',
|
||||
icon: icons.CopyOutlined
|
||||
},
|
||||
{
|
||||
label: 'common.button.start',
|
||||
key: 'start',
|
||||
icon: icons.Play
|
||||
},
|
||||
{
|
||||
label: 'models.table.button.apiAccessInfo',
|
||||
key: 'api',
|
||||
icon: icons.ApiOutlined
|
||||
},
|
||||
{
|
||||
label: 'common.button.stop',
|
||||
key: 'stop',
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
import { PageAction } from '@/config';
|
||||
import { PageActionType } from '@/config/types';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { useState } from 'react';
|
||||
import { ListItem } from '../config/types';
|
||||
|
||||
const useEditDeployment = () => {
|
||||
const intl = useIntl();
|
||||
const [openModalStatus, setOpenModalStatus] = useState<{
|
||||
open: boolean;
|
||||
action: PageActionType;
|
||||
currentData: {
|
||||
isGGUF: boolean;
|
||||
data: any; // for form data
|
||||
row: ListItem;
|
||||
realAction?: PageActionType; // added action here for copy action
|
||||
};
|
||||
title: string;
|
||||
}>({
|
||||
open: false,
|
||||
action: PageAction.EDIT,
|
||||
currentData: {
|
||||
isGGUF: false,
|
||||
data: {},
|
||||
row: {} as ListItem
|
||||
},
|
||||
title: ''
|
||||
});
|
||||
|
||||
const openEditModal = (formData: any, row: ListItem) => {
|
||||
setOpenModalStatus({
|
||||
open: true,
|
||||
action: PageAction.EDIT,
|
||||
currentData: {
|
||||
isGGUF: false,
|
||||
data: formData,
|
||||
row: row
|
||||
},
|
||||
title: intl.formatMessage({ id: 'models.title.edit' })
|
||||
});
|
||||
};
|
||||
|
||||
const openDuplicateModal = (formData: any, row: ListItem) => {
|
||||
setOpenModalStatus({
|
||||
open: true,
|
||||
action: PageAction.EDIT,
|
||||
currentData: {
|
||||
isGGUF: false,
|
||||
data: {
|
||||
...formData,
|
||||
name: `${formData.name}-copy`
|
||||
},
|
||||
row: row,
|
||||
realAction: PageAction.COPY
|
||||
},
|
||||
title: intl.formatMessage({ id: 'models.title.duplicate' })
|
||||
});
|
||||
};
|
||||
|
||||
const closeModal = () => {
|
||||
setOpenModalStatus({
|
||||
open: false,
|
||||
action: PageAction.EDIT,
|
||||
currentData: {
|
||||
isGGUF: false,
|
||||
data: {},
|
||||
row: {} as ListItem
|
||||
},
|
||||
title: ''
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
openEditModalStatus: openModalStatus,
|
||||
setOpenEditModalStatus: setOpenModalStatus,
|
||||
openEditModal: openEditModal,
|
||||
openDuplicateModal: openDuplicateModal,
|
||||
closeEditModal: closeModal
|
||||
};
|
||||
};
|
||||
|
||||
export default useEditDeployment;
|
||||
@@ -3,8 +3,10 @@ import AutoTooltip from '@/components/auto-tooltip';
|
||||
import DropdownButtons from '@/components/drop-down-buttons';
|
||||
import { SealColumnProps } from '@/components/seal-table/types';
|
||||
import { OPENAI_COMPATIBLE, tableSorter } from '@/config/settings';
|
||||
import { TargetStatusValueMap } from '@/pages/model-routes/config';
|
||||
import { QuestionCircleOutlined } from '@ant-design/icons';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { useMemoizedFn } from 'ahooks';
|
||||
import { Tooltip } from 'antd';
|
||||
import dayjs from 'dayjs';
|
||||
import _ from 'lodash';
|
||||
@@ -13,24 +15,6 @@ import ModelTag from '../../_components/model-tag';
|
||||
import { ActionList, generateSource } from '../config/button-actions';
|
||||
import { ListItem } from '../config/types';
|
||||
|
||||
const setModelActionList = (record: any) => {
|
||||
return _.filter(ActionList, (action: any) => {
|
||||
if (action.key === 'chat' || action.key === 'api') {
|
||||
return record.ready_replicas > 0;
|
||||
}
|
||||
|
||||
if (action.key === 'start') {
|
||||
return record.replicas === 0;
|
||||
}
|
||||
|
||||
if (action.key === 'stop') {
|
||||
return record.replicas > 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
interface ModelsColumnsHookProps {
|
||||
handleSelect: (val: string, record: ListItem) => void;
|
||||
sortOrder: string[];
|
||||
@@ -43,10 +27,36 @@ interface ModelsColumnsHookProps {
|
||||
const useModelsColumns = ({
|
||||
handleSelect,
|
||||
clusterList,
|
||||
sortOrder
|
||||
}: ModelsColumnsHookProps): SealColumnProps[] => {
|
||||
sortOrder,
|
||||
targetList
|
||||
}: ModelsColumnsHookProps & { targetList: any[] }): SealColumnProps[] => {
|
||||
const intl = useIntl();
|
||||
|
||||
const setModelActionList = useMemoizedFn((record: any) => {
|
||||
return _.filter(ActionList, (action: any) => {
|
||||
if (action.key === 'chat') {
|
||||
return (
|
||||
record.ready_replicas > 0 &&
|
||||
targetList?.find(
|
||||
(target) =>
|
||||
target.model_id === record.id &&
|
||||
target.state === TargetStatusValueMap.Active
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (action.key === 'start') {
|
||||
return record.replicas === 0;
|
||||
}
|
||||
|
||||
if (action.key === 'stop') {
|
||||
return record.replicas > 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
});
|
||||
|
||||
return useMemo(() => {
|
||||
return [
|
||||
{
|
||||
@@ -137,7 +147,7 @@ const useModelsColumns = ({
|
||||
key: 'operation',
|
||||
dataIndex: 'operation',
|
||||
span: 3,
|
||||
render: (text, record) => (
|
||||
render: (text: any, record: ListItem) => (
|
||||
<DropdownButtons
|
||||
items={setModelActionList(record)}
|
||||
onSelect={(val) => handleSelect(val, record)}
|
||||
|
||||
Reference in New Issue
Block a user