diff --git a/src/pages/llmodels/components/deployment/deploy-builtin-modal.tsx b/src/pages/llmodels/components/deployment/deploy-builtin-modal.tsx index 606b1f0c..ecbc32cf 100644 --- a/src/pages/llmodels/components/deployment/deploy-builtin-modal.tsx +++ b/src/pages/llmodels/components/deployment/deploy-builtin-modal.tsx @@ -59,7 +59,7 @@ type AddModalProps = { source: SourceType; width?: string | number; current?: any; - onOk: (values: FormData) => void; + onOk: (values: FormData) => void | Promise; onCancel: () => void; }; @@ -104,8 +104,14 @@ const AddModal: React.FC = (props) => { const specListRef = useRef([]); const noCompatibleGPUsRef = useRef(false); const backendOptionsCache = useRef([]); + const [loading, setLoading] = useState(false); + const submitloadingRef = useRef(false); const handleSumit = () => { + if (submitloadingRef.current) { + return; + } + submitloadingRef.current = true; form.current?.submit?.(); }; @@ -115,7 +121,11 @@ const AddModal: React.FC = (props) => { return; } submitAnyway.current = true; - form.current?.submit?.(); + handleSumit(); + }; + + const onFinishFailed = () => { + submitloadingRef.current = false; }; const generateSubmitData = (formData: FormData) => { @@ -348,7 +358,13 @@ const AddModal: React.FC = (props) => { ..._.omit(selectSpecRef.current, ['name']), ...values }; - onOk(data); + setLoading(true); + try { + await onOk(data); + } finally { + setLoading(false); + submitloadingRef.current = false; + } }; const handleCancel = () => { @@ -447,6 +463,7 @@ const AddModal: React.FC = (props) => { = (props) => { source={source} action={action} onOk={handleOk} + onFinishFailed={onFinishFailed} ref={form} isGGUF={isGGUF} formKey={DeployFormKeyMap.CATALOG} diff --git a/src/pages/llmodels/components/deployment/deploy-modal.tsx b/src/pages/llmodels/components/deployment/deploy-modal.tsx index aebd9804..d72c20fe 100644 --- a/src/pages/llmodels/components/deployment/deploy-modal.tsx +++ b/src/pages/llmodels/components/deployment/deploy-modal.tsx @@ -146,6 +146,8 @@ const AddModal: FC = (props) => { const requestModelIdRef = useRef(0); const currentSelectedModel = useRef({}); const flatBackendOptionsRef = useRef([]); + const [loading, setLoading] = useState(false); + const submitloadingRef = useRef(false); const { run: fetchModelFiles } = useDeferredRequest( () => modelFileRef.current?.fetchModelFiles?.(), @@ -422,22 +424,33 @@ const AddModal: FC = (props) => { }; const handleOnOk = async (allValues: FormData) => { - onOk(allValues); + setLoading(true); + await onOk(allValues); + setLoading(false); + submitloadingRef.current = false; + }; + + const handleSumit = () => { + if (submitloadingRef.current) { + return; + } + submitloadingRef.current = true; + form.current?.submit?.(); }; const handleSubmitAnyway = async () => { submitAnyway.current = true; - form.current?.submit?.(); - }; - - const handleSumit = () => { - form.current?.submit?.(); + handleSumit(); }; const handleSetIsGGUF = async (flag: boolean) => { setIsGGUF(flag); }; + const onFinishFailed = () => { + submitloadingRef.current = false; + }; + const handleBackendChange = async (backend: string) => { const data = form.current.form.getFieldsValue?.(); const res = handleBackendChangeBefore(data); @@ -660,6 +673,7 @@ const AddModal: FC = (props) => { = (props) => { onOk={handleOnOk} ref={form} isGGUF={isGGUF} + onFinishFailed={onFinishFailed} onBackendChange={handleBackendChange} onValuesChange={onValuesChange} clearCacheFormValues={clearCacheFormValues} diff --git a/src/pages/llmodels/components/deployment/update-modal.tsx b/src/pages/llmodels/components/deployment/update-modal.tsx index 40d9c542..d49a6218 100644 --- a/src/pages/llmodels/components/deployment/update-modal.tsx +++ b/src/pages/llmodels/components/deployment/update-modal.tsx @@ -3,7 +3,7 @@ import { PageActionType } from '@/config/types'; import { ColumnWrapper, GSDrawer, ModalFooter } from '@gpustack/core-ui'; import { useIntl } from '@umijs/max'; import _ from 'lodash'; -import React, { useEffect, useRef } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { DeployFormKeyMap, DO_NOT_NOTIFY_RECREATE, @@ -29,7 +29,7 @@ type AddModalProps = { number, { provider: string; state: string | number } >[]; - onOk: (values: FormData) => void; + onOk: (values: FormData) => void | Promise; onCancel: () => void; }; @@ -60,6 +60,8 @@ const UpdateModal: React.FC = (props) => { const formRef = useRef(null); const submitAnyway = useRef(false); const originFormData = useRef(null); + const [loading, setLoading] = useState(false); + const submitloadingRef = useRef(false); const setOriginalFormData = () => { if (!originFormData.current) { @@ -157,12 +159,20 @@ const UpdateModal: React.FC = (props) => { }; const handleSumit = () => { + if (submitloadingRef.current) { + return; + } + submitloadingRef.current = true; formRef.current?.submit(); }; const handleSubmitAnyway = async () => { submitAnyway.current = true; - formRef.current?.submit?.(); + handleSumit(); + }; + + const onFinishFailed = () => { + submitloadingRef.current = false; }; const handleOk = async (formdata: FormData) => { @@ -182,7 +192,13 @@ const UpdateModal: React.FC = (props) => { } : {}) }; - onOk(submitData); + setLoading(true); + try { + await onOk(submitData); + } finally { + setLoading(false); + submitloadingRef.current = false; + } }; const handleManulOnValuesChange = (changedValues: any, allValues: any) => { @@ -266,6 +282,7 @@ const UpdateModal: React.FC = (props) => { style={ModalFooterStyle} onCancel={onCancel} onOk={handleSumit} + loading={loading} > } @@ -278,6 +295,7 @@ const UpdateModal: React.FC = (props) => { realAction={realAction} clusterList={clusterList} onOk={handleOk} + onFinishFailed={onFinishFailed} ref={formRef} isGGUF={isGGUF} onBackendChange={handleAsyncBackendChange} diff --git a/src/pages/llmodels/components/model-source/search-result.tsx b/src/pages/llmodels/components/model-source/search-result.tsx index 665244fa..f2ff4b44 100644 --- a/src/pages/llmodels/components/model-source/search-result.tsx +++ b/src/pages/llmodels/components/model-source/search-result.tsx @@ -76,15 +76,15 @@ const SearchResult: React.FC = (props) => { > } description={ - source === modelSourceMap.huggingface_value ? ( -
+
+ + {intl.formatMessage({ id: 'models.search.networkerror' })} + + - {intl.formatMessage({ id: 'models.search.networkerror' })} + {intl.formatMessage({ id: 'models.search.hfvisit' })} - - - {intl.formatMessage({ id: 'models.search.hfvisit' })} - + {source === modelSourceMap.huggingface_value ? ( - -
- ) : null + ) : ( + + )} + +
} /> ); diff --git a/src/pages/llmodels/forms/index.tsx b/src/pages/llmodels/forms/index.tsx index 3d222209..7d9d96d3 100644 --- a/src/pages/llmodels/forms/index.tsx +++ b/src/pages/llmodels/forms/index.tsx @@ -66,6 +66,7 @@ interface DataFormProps { onOk: (values: FormData) => void; onBackendChange?: (value: string) => void; onClusterChange?: (value: number) => void; + onFinishFailed?: (errorInfo: any) => void; } const TABKeysMap = { @@ -91,6 +92,7 @@ const DataForm: React.FC = forwardRef((props, ref) => { onSourceChange, onValuesChange, onClusterChange, + onFinishFailed, onOk } = props; const { getScrollElementScrollableHeight } = useWrapperContext(); @@ -285,6 +287,7 @@ const DataForm: React.FC = forwardRef((props, ref) => { const handleOnFinishFailed = (errorInfo: any) => { setSubmitAttempted(true); + onFinishFailed?.(errorInfo); console.log('Failed:', errorInfo); const { errorFields } = errorInfo; if (errorFields && errorFields.length > 0) {