@@ -63,6 +63,7 @@ import {
6363 Typography ,
6464 theme ,
6565} from 'antd' ;
66+ import type { FormInstance } from 'antd' ;
6667import type { CheckboxChangeEvent } from 'antd/es/checkbox' ;
6768import {
6869 BAIAvailablePresetSelect ,
@@ -850,7 +851,7 @@ const DeploymentAddRevisionModal: React.FC<DeploymentAddRevisionModalProps> = ({
850851 }
851852 } ;
852853
853- const handleCustomFinish = ( values : FormValues ) => {
854+ const handleCustomFinish = ( values : FormValues ) : void => {
854855 // `setFields` raises an error programmatically — antd's
855856 // `scrollToFirstError` only fires from `onFinishFailed`, so we have
856857 // to nudge the scroll explicitly here.
@@ -966,113 +967,113 @@ const DeploymentAddRevisionModal: React.FC<DeploymentAddRevisionModalProps> = ({
966967 ? ( values . commandModelMount ?? '/models' )
967968 : values . mountDestination || '/models' ;
968969
969- customForm . validateFields ( ) . then ( ( ) => {
970- setIsSubmitting ( true ) ;
971- commitAdd ( {
972- variables : {
973- input : {
974- deploymentId : toLocalId ( deploymentId ) ?? deploymentId ,
975- clusterConfig : {
976- mode : clusterMode ,
977- size : values . cluster_size ,
978- } ,
979- resourceConfig : {
980- resourceGroup : { name : values . resourceGroup } ,
981- resourceSlots : { entries : slotEntries } ,
982- resourceOpts :
983- optsEntries . length > 0 ? { entries : optsEntries } : null ,
984- } ,
985- image : { id : decodedImageId } ,
986- modelRuntimeConfig : {
987- runtimeVariantId : values . runtimeVariantId ,
988- inferenceRuntimeConfig : null ,
989- environ :
990- environEntries . length > 0 ? { entries : environEntries } : null ,
991- } ,
992- modelMountConfig : {
993- vfolderId : convertToUUID ( values . modelFolderId ) ,
994- mountDestination,
995- definitionPath : values . definitionPath ,
996- } ,
997- modelDefinition,
998- extraMounts : extraMounts . length > 0 ? extraMounts : null ,
999- options : { autoActivate } ,
970+ setIsSubmitting ( true ) ;
971+ commitAdd ( {
972+ variables : {
973+ input : {
974+ deploymentId : toLocalId ( deploymentId ) ?? deploymentId ,
975+ clusterConfig : {
976+ mode : clusterMode ,
977+ size : values . cluster_size ,
1000978 } ,
979+ resourceConfig : {
980+ resourceGroup : { name : values . resourceGroup } ,
981+ resourceSlots : { entries : slotEntries } ,
982+ resourceOpts :
983+ optsEntries . length > 0 ? { entries : optsEntries } : null ,
984+ } ,
985+ image : { id : decodedImageId } ,
986+ modelRuntimeConfig : {
987+ runtimeVariantId : values . runtimeVariantId ,
988+ inferenceRuntimeConfig : null ,
989+ environ :
990+ environEntries . length > 0 ? { entries : environEntries } : null ,
991+ } ,
992+ modelMountConfig : {
993+ vfolderId : convertToUUID ( values . modelFolderId ) ,
994+ mountDestination,
995+ definitionPath : values . definitionPath ,
996+ } ,
997+ modelDefinition,
998+ extraMounts : extraMounts . length > 0 ? extraMounts : null ,
999+ options : { autoActivate } ,
10011000 } ,
1002- onCompleted : ( _ , errors ) => {
1003- setIsSubmitting ( false ) ;
1004- if ( errors && errors . length > 0 ) {
1005- const err = errors [ 0 ] ;
1006- const isInProgress = err ?. message ?. includes (
1007- 'Another deployment is already in progress' ,
1008- ) ;
1009- message . error (
1010- isInProgress
1011- ? t ( 'deployment.AnotherDeploymentInProgress' )
1012- : ( err ?. message ?? t ( 'general.ErrorOccurred' ) ) ,
1013- ) ;
1014- return ;
1015- }
1016- customForm . resetFields ( ) ;
1017- onRequestClose ( true ) ;
1018- } ,
1019- onError : ( err ) => {
1020- setIsSubmitting ( false ) ;
1021- const isInProgress = err . message ?. includes (
1001+ } ,
1002+ onCompleted : ( _ , errors ) => {
1003+ setIsSubmitting ( false ) ;
1004+ if ( errors && errors . length > 0 ) {
1005+ const err = errors [ 0 ] ;
1006+ const isInProgress = err ?. message ?. includes (
10221007 'Another deployment is already in progress' ,
10231008 ) ;
10241009 message . error (
10251010 isInProgress
10261011 ? t ( 'deployment.AnotherDeploymentInProgress' )
1027- : ( err . message ?? t ( 'general.ErrorOccurred' ) ) ,
1012+ : ( err ? .message ?? t ( 'general.ErrorOccurred' ) ) ,
10281013 ) ;
1029- } ,
1030- } ) ;
1014+ return ;
1015+ }
1016+ customForm . resetFields ( ) ;
1017+ onRequestClose ( true ) ;
1018+ } ,
1019+ onError : ( err ) => {
1020+ setIsSubmitting ( false ) ;
1021+ const isInProgress = err . message ?. includes (
1022+ 'Another deployment is already in progress' ,
1023+ ) ;
1024+ message . error (
1025+ isInProgress
1026+ ? t ( 'deployment.AnotherDeploymentInProgress' )
1027+ : ( err . message ?? t ( 'general.ErrorOccurred' ) ) ,
1028+ ) ;
1029+ } ,
10311030 } ) ;
10321031 } ;
10331032
1034- const handlePresetFinish = ( ) => {
1033+ const handlePresetFinish = ( values : PresetFormValues ) : void => {
10351034 if ( ! projectId ) {
10361035 message . error ( t ( 'general.ErrorOccurred' ) ) ;
10371036 return ;
10381037 }
1039- presetForm . validateFields ( ) . then ( ( values ) => {
1040- setIsSubmitting ( true ) ;
1041- commitDeploy ( {
1042- variables : {
1043- vfolderId : convertToUUID ( values . modelFolderId ) ,
1044- input : {
1045- projectId,
1046- revisionPresetId : values . revisionPresetId ,
1047- resourceGroup : values . resourceGroup ,
1048- desiredReplicaCount : 1 ,
1049- } ,
1038+ setIsSubmitting ( true ) ;
1039+ commitDeploy ( {
1040+ variables : {
1041+ vfolderId : convertToUUID ( values . modelFolderId ) ,
1042+ input : {
1043+ projectId,
1044+ revisionPresetId : values . revisionPresetId ,
1045+ resourceGroup : values . resourceGroup ,
1046+ desiredReplicaCount : 1 ,
10501047 } ,
1051- onCompleted : ( response , errors ) => {
1052- setIsSubmitting ( false ) ;
1053- if ( errors && errors . length > 0 ) {
1054- const errMsg = errors . map ( ( e ) => e . message ) . join ( '\n' ) ;
1055- logger . error (
1056- '[DeploymentAddRevisionModal] deployVfolderV2 returned errors' ,
1057- errors ,
1058- ) ;
1059- message . error ( errMsg || t ( 'modelStore.DeployFailed' ) ) ;
1060- return ;
1061- }
1062- const newDeploymentId = String ( response . deployVfolderV2 . deploymentId ) ;
1063- message . success ( t ( 'modelStore.DeploySuccess' ) ) ;
1064- onRequestClose ( true ) ;
1065- navigate ( `/deployments/${ newDeploymentId } ` ) ;
1066- } ,
1067- onError : ( error ) => {
1068- setIsSubmitting ( false ) ;
1048+ } ,
1049+ onCompleted : ( response , errors ) => {
1050+ setIsSubmitting ( false ) ;
1051+ if ( errors && errors . length > 0 ) {
1052+ const errMsg = errors . map ( ( e ) => e . message ) . join ( '\n' ) ;
10691053 logger . error (
1070- '[DeploymentAddRevisionModal] deployVfolderV2 failed ' ,
1071- error ,
1054+ '[DeploymentAddRevisionModal] deployVfolderV2 returned errors ' ,
1055+ errors ,
10721056 ) ;
1073- message . error ( error . message || t ( 'modelStore.DeployFailed' ) ) ;
1074- } ,
1075- } ) ;
1057+ message . error ( errMsg || t ( 'modelStore.DeployFailed' ) ) ;
1058+ return ;
1059+ }
1060+ const newDeploymentId = response . deployVfolderV2 ?. deploymentId
1061+ ? String ( response . deployVfolderV2 . deploymentId )
1062+ : undefined ;
1063+ message . success ( t ( 'modelStore.DeploySuccess' ) ) ;
1064+ onRequestClose ( true ) ;
1065+ if ( newDeploymentId ) {
1066+ navigate ( `/deployments/${ newDeploymentId } ` ) ;
1067+ }
1068+ } ,
1069+ onError : ( error ) => {
1070+ setIsSubmitting ( false ) ;
1071+ logger . error (
1072+ '[DeploymentAddRevisionModal] deployVfolderV2 failed' ,
1073+ error ,
1074+ ) ;
1075+ message . error ( error . message || t ( 'modelStore.DeployFailed' ) ) ;
1076+ } ,
10761077 } ) ;
10771078 } ;
10781079
@@ -1094,16 +1095,14 @@ const DeploymentAddRevisionModal: React.FC<DeploymentAddRevisionModalProps> = ({
10941095 } ;
10951096
10961097 const handleOk = ( ) => {
1098+ // Let antd's built-in submit flow handle validation routing:
1099+ // success → `onFinish` (handle*Finish), failure → `onFinishFailed`
1100+ // (handleFinishFailed). Calling `validateFields()` separately and
1101+ // swallowing rejections in a `.catch` would silently drop submits
1102+ // when validation fails — including transient races during the
1103+ // BAIProjectResourceGroupSelect auto-select.
10971104 const activeForm = effectiveMode === 'preset' ? presetForm : customForm ;
1098- activeForm
1099- . validateFields ( )
1100- . then ( ( ) => {
1101- activeForm . submit ( ) ;
1102- } )
1103- . catch ( ( ) => {
1104- // Validation failed — the form's `onFinishFailed` handler scrolls
1105- // to the first errored field.
1106- } ) ;
1105+ activeForm . submit ( ) ;
11071106 } ;
11081107
11091108 const okText =
@@ -1187,6 +1186,7 @@ const DeploymentAddRevisionModal: React.FC<DeploymentAddRevisionModalProps> = ({
11871186 layout = "vertical"
11881187 style = { { marginTop : token . marginXS } }
11891188 onFinish = { handlePresetFinish }
1189+ onFinishFailed = { handleFinishFailed }
11901190 initialValues = { {
11911191 modelFolderId : defaultModelFolderId ,
11921192 } }
@@ -1208,7 +1208,7 @@ const DeploymentAddRevisionModal: React.FC<DeploymentAddRevisionModalProps> = ({
12081208 />
12091209 </ Form . Item >
12101210 < Form . Item dependencies = { [ 'revisionPresetId' ] } noStyle >
1211- { ( { getFieldValue } ) => {
1211+ { ( { getFieldValue } : FormInstance < PresetFormValues > ) => {
12121212 const selectedId = getFieldValue ( 'revisionPresetId' ) ;
12131213 return (
12141214 < Space . Compact >
@@ -1345,7 +1345,7 @@ const DeploymentAddRevisionModal: React.FC<DeploymentAddRevisionModalProps> = ({
13451345 </ Form . Item >
13461346
13471347 < Form . Item dependencies = { [ 'runtimeVariantId' ] } noStyle >
1348- { ( { getFieldValue } ) => {
1348+ { ( { getFieldValue } : FormInstance < FormValues > ) => {
13491349 const variantId = getFieldValue ( 'runtimeVariantId' ) ;
13501350 const variantName = runtimeVariantNameMap [ variantId ] ;
13511351 if ( ! variantName || variantName === 'custom' ) return null ;
@@ -1376,7 +1376,7 @@ const DeploymentAddRevisionModal: React.FC<DeploymentAddRevisionModalProps> = ({
13761376 </ Form . Item >
13771377
13781378 < Form . Item dependencies = { [ 'runtimeVariantId' ] } noStyle >
1379- { ( { getFieldValue } ) => {
1379+ { ( { getFieldValue } : FormInstance < FormValues > ) => {
13801380 const variantId = getFieldValue ( 'runtimeVariantId' ) ;
13811381 const variantName = runtimeVariantNameMap [ variantId ] ;
13821382 if ( variantName !== 'custom' ) {
@@ -1400,7 +1400,7 @@ const DeploymentAddRevisionModal: React.FC<DeploymentAddRevisionModalProps> = ({
14001400 />
14011401 </ Form . Item >
14021402 < Form . Item dependencies = { [ 'customDefinitionMode' ] } noStyle >
1403- { ( { getFieldValue : getField } ) =>
1403+ { ( { getFieldValue : getField } : FormInstance < FormValues > ) =>
14041404 getField ( 'customDefinitionMode' ) === 'command' ? (
14051405 < >
14061406 < Form . Item
@@ -1552,7 +1552,7 @@ const DeploymentAddRevisionModal: React.FC<DeploymentAddRevisionModalProps> = ({
15521552 'mount_ids' ,
15531553 ] }
15541554 >
1555- { ( { getFieldValue } ) => {
1555+ { ( { getFieldValue } : FormInstance < FormValues > ) => {
15561556 const modelFolderId = getFieldValue ( 'modelFolderId' ) ;
15571557 const modelFolderIdNoDash = modelFolderId
15581558 ? String ( modelFolderId ) . replace ( / - / g, '' )
0 commit comments