Skip to content

Commit d0d953e

Browse files
committed
refactor(FR-2494): replace BAIConfirmModalWithInput with modal.confirm for delete
1 parent ace98d0 commit d0d953e

25 files changed

Lines changed: 77 additions & 39 deletions

react/src/components/AutoScalingRuleEditorModal.tsx

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ const AutoScalingRuleEditorModal: React.FC<AutoScalingRuleEditorModalProps> = ({
434434
for (const error of errorMsgList) {
435435
message.error(error);
436436
}
437-
onRequestClose(false);
437+
// Keep modal open so the user can correct the input and retry
438438
return;
439439
}
440440
message.success(t('autoScalingRule.SuccessfullyUpdated'));
@@ -443,7 +443,7 @@ const AutoScalingRuleEditorModal: React.FC<AutoScalingRuleEditorModalProps> = ({
443443
},
444444
onError: (error) => {
445445
message.error(error.message);
446-
onRequestClose(false);
446+
// Keep modal open so the user can correct the input and retry
447447
},
448448
});
449449
} else {
@@ -471,7 +471,7 @@ const AutoScalingRuleEditorModal: React.FC<AutoScalingRuleEditorModalProps> = ({
471471
for (const error of errorMsgList) {
472472
message.error(error);
473473
}
474-
onRequestClose(false);
474+
// Keep modal open so the user can correct the input and retry
475475
return;
476476
}
477477
message.success(t('autoScalingRule.SuccessfullyCreated'));
@@ -480,7 +480,7 @@ const AutoScalingRuleEditorModal: React.FC<AutoScalingRuleEditorModalProps> = ({
480480
},
481481
onError: (error) => {
482482
message.error(error.message);
483-
onRequestClose(false);
483+
// Keep modal open so the user can correct the input and retry
484484
},
485485
});
486486
}
@@ -667,15 +667,16 @@ const AutoScalingRuleEditorModal: React.FC<AutoScalingRuleEditorModalProps> = ({
667667
formRef.current?.setFieldsValue({
668668
metricName: preset.metricName,
669669
});
670-
// Auto-apply timeWindow from preset; always update to avoid
671-
// stale values when switching between presets
670+
// Auto-apply timeWindow from preset only when the preset
671+
// provides a valid value; otherwise keep the existing value
672+
// (e.g. the default 300) to avoid unexpected clearing.
672673
const tw =
673674
preset.timeWindow != null
674675
? Number(preset.timeWindow)
675676
: undefined;
676-
formRef.current?.setFieldsValue({
677-
timeWindow: tw != null && !isNaN(tw) ? tw : undefined,
678-
});
677+
if (tw != null && !isNaN(tw)) {
678+
formRef.current?.setFieldsValue({ timeWindow: tw });
679+
}
679680
}
680681
}}
681682
placeholder={t('autoScalingRule.SelectPrometheusPreset')}

react/src/components/AutoScalingRuleList.tsx

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ interface AutoScalingRuleListNodesProps extends Omit<
137137
isEndpointDestroying: boolean;
138138
isOwnedByCurrentUser: boolean;
139139
onEditRule: (id: string) => void;
140-
onDeleteRule: (id: string) => void;
140+
onDeleteRule: (id: string, metricName: string) => void;
141141
}
142142

143143
const AutoScalingRuleListNodes: React.FC<AutoScalingRuleListNodesProps> = ({
@@ -211,7 +211,7 @@ const AutoScalingRuleListNodes: React.FC<AutoScalingRuleListNodesProps> = ({
211211
icon: <DeleteOutlined />,
212212
type: 'danger',
213213
disabled: isEndpointDestroying || !isOwnedByCurrentUser,
214-
onClick: () => onDeleteRule(row.id),
214+
onClick: () => onDeleteRule(row.id, row.metricName ?? ''),
215215
},
216216
]}
217217
/>
@@ -320,12 +320,14 @@ interface AutoScalingRuleListProps {
320320
deploymentId: string; // Relay global ID (e.g., toGlobalId('ModelDeployment', uuid))
321321
isEndpointDestroying: boolean;
322322
isOwnedByCurrentUser: boolean;
323+
fetchKey?: string;
323324
}
324325

325326
const AutoScalingRuleList: React.FC<AutoScalingRuleListProps> = ({
326327
deploymentId,
327328
isEndpointDestroying,
328329
isOwnedByCurrentUser,
330+
fetchKey: parentFetchKey,
329331
}) => {
330332
'use memo';
331333
const { t } = useTranslation();
@@ -402,6 +404,7 @@ const AutoScalingRuleList: React.FC<AutoScalingRuleListProps> = ({
402404
edges {
403405
node {
404406
id
407+
metricName
405408
...AutoScalingRuleListNodesFragment
406409
...AutoScalingRuleEditorModalFragment
407410
}
@@ -413,7 +416,7 @@ const AutoScalingRuleList: React.FC<AutoScalingRuleListProps> = ({
413416
deferredQueryVariables,
414417
{
415418
fetchPolicy: 'store-and-network',
416-
fetchKey,
419+
fetchKey: parentFetchKey ? `${parentFetchKey}_${fetchKey}` : fetchKey,
417420
},
418421
);
419422

@@ -470,33 +473,39 @@ const AutoScalingRuleList: React.FC<AutoScalingRuleListProps> = ({
470473
});
471474
};
472475

473-
const handleDeleteRule = (ruleId: string) => {
476+
const handleDeleteRule = (ruleId: string, metricName: string) => {
474477
modal.confirm({
475478
title: t('dialog.warning.CannotBeUndone'),
479+
content: t('autoScalingRule.ConfirmDeleteAutoScalingRule', {
480+
autoScalingRule: metricName,
481+
}),
476482
okText: t('button.Delete'),
477483
okButtonProps: { danger: true },
478-
onOk: () => {
479-
commitDeleteMutation({
480-
variables: { input: { id: toLocalId(ruleId) } },
481-
onCompleted: (_res, errors) => {
482-
if (errors && errors.length > 0) {
483-
for (const error of errors) {
484-
message.error(error.message || t('dialog.ErrorOccurred'));
484+
onOk: () =>
485+
new Promise<void>((resolve, reject) => {
486+
commitDeleteMutation({
487+
variables: { input: { id: toLocalId(ruleId) } },
488+
onCompleted: (_res, errors) => {
489+
if (errors && errors.length > 0) {
490+
for (const error of errors) {
491+
message.error(error.message || t('dialog.ErrorOccurred'));
492+
}
493+
reject();
494+
} else {
495+
handleRefetch();
496+
message.success({
497+
key: 'autoscaling-rule-deleted',
498+
content: t('autoScalingRule.SuccessfullyDeleted'),
499+
});
500+
resolve();
485501
}
486-
} else {
487-
setEditingRuleId(null);
488-
handleRefetch();
489-
message.success({
490-
key: 'autoscaling-rule-deleted',
491-
content: t('autoScalingRule.SuccessfullyDeleted'),
492-
});
493-
}
494-
},
495-
onError: (error) => {
496-
message.error(error?.message || t('dialog.ErrorOccurred'));
497-
},
498-
});
499-
},
502+
},
503+
onError: (error) => {
504+
message.error(error?.message || t('dialog.ErrorOccurred'));
505+
reject();
506+
},
507+
});
508+
}),
500509
});
501510
};
502511

react/src/components/DefaultProviders.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -220,17 +220,17 @@ export const DefaultProvidersForReactRoot: React.FC<{
220220

221221
const themeConfig = useCustomThemeConfig();
222222

223+
const currentLocale =
224+
buiLanguages[lang as keyof typeof buiLanguages] ?? buiLanguages['en'];
225+
223226
return (
224227
<>
225228
<style>{indexCss}</style>
226229
{RelayEnvironment && (
227230
<RelayEnvironmentProvider environment={RelayEnvironment}>
228231
<QueryClientProvider client={queryClient}>
229232
<BAIConfigProvider
230-
locale={
231-
buiLanguages[lang as keyof typeof buiLanguages] ??
232-
buiLanguages['en']
233-
}
233+
locale={currentLocale}
234234
theme={{
235235
...(isDarkMode
236236
? { ...themeConfig?.dark }
@@ -254,6 +254,11 @@ export const DefaultProvidersForReactRoot: React.FC<{
254254
},
255255
}}
256256
form={{
257+
// Explicitly set validateMessages from the antd locale so form
258+
// validation errors always appear in the user's selected language
259+
// (antd's built-in default falls back to English otherwise).
260+
validateMessages:
261+
currentLocale.antdLocale?.Form?.defaultValidateMessages,
257262
requiredMark: (label, { required }) => (
258263
<>
259264
{label}

react/src/pages/EndpointDetailPage.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,8 @@ const EndpointDetailPage: React.FC<EndpointDetailPageProps> = () => {
346346
autoScalingRules_after: undefined,
347347
autoScalingRules_first: undefined,
348348
autoScalingRules_last: undefined,
349-
skipScalingRules: !isSupportAutoScalingRule,
349+
skipScalingRules:
350+
!isSupportAutoScalingRule || isSupportPrometheusAutoScalingRule,
350351
deploymentId: toGlobalId('ModelDeployment', serviceId || ''),
351352
routeFilter: {
352353
status: (deferredRouteStatusCategory === 'running'
@@ -754,6 +755,7 @@ const EndpointDetailPage: React.FC<EndpointDetailPageProps> = () => {
754755
!endpoint?.created_user_email ||
755756
endpoint?.created_user_email === currentUser.email
756757
}
758+
fetchKey={fetchKey}
757759
/>
758760
) : (
759761
<AutoScalingRuleListLegacy

resources/i18n/de.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@
205205
"TimeWindow": "Zeitfenster",
206206
"TimeWindowSeconds": "{{value}}s",
207207
"TimeWindowTooltip": "Das Zeitfenster in Sekunden zur Auswertung der Skalierungsmetrik.",
208+
"TypeMetricNameToDelete": "Geben Sie \"{{ metricName }}\" ein, um die Löschung zu bestätigen",
208209
"Upper": "Oberer"
209210
},
210211
"button": {

resources/i18n/el.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@
205205
"TimeWindow": "Χρονικό Παράθυρο",
206206
"TimeWindowSeconds": "{{value}}s",
207207
"TimeWindowTooltip": "Το χρονικό παράθυρο σε δευτερόλεπτα για αξιολόγηση της μετρικής κλιμάκωσης.",
208+
"TypeMetricNameToDelete": "Πληκτρολογήστε \"{{ metricName }}\" για να επιβεβαιώσετε τη διαγραφή",
208209
"Upper": "Άνω"
209210
},
210211
"button": {

resources/i18n/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@
205205
"TimeWindow": "Time Window",
206206
"TimeWindowSeconds": "{{value}}s",
207207
"TimeWindowTooltip": "The time window in seconds for evaluating the scaling metric.",
208+
"TypeMetricNameToDelete": "Type \"{{ metricName }}\" to confirm deletion",
208209
"Upper": "Upper"
209210
},
210211
"button": {

resources/i18n/es.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@
205205
"TimeWindow": "Ventana de tiempo",
206206
"TimeWindowSeconds": "{{value}}s",
207207
"TimeWindowTooltip": "La ventana de tiempo en segundos para evaluar la métrica de escalado.",
208+
"TypeMetricNameToDelete": "Escriba \"{{ metricName }}\" para confirmar la eliminación",
208209
"Upper": "Superior"
209210
},
210211
"button": {

resources/i18n/fi.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@
205205
"TimeWindow": "Aikaikkuna",
206206
"TimeWindowSeconds": "{{value}}s",
207207
"TimeWindowTooltip": "Aikaikkuna sekunneissa skaalausmetriikan arviointia varten.",
208+
"TypeMetricNameToDelete": "Kirjoita \"{{ metricName }}\" vahvistaaksesi poistamisen",
208209
"Upper": "Yläraja"
209210
},
210211
"button": {

resources/i18n/fr.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@
205205
"TimeWindow": "Fenêtre temporelle",
206206
"TimeWindowSeconds": "{{value}}s",
207207
"TimeWindowTooltip": "La fenêtre temporelle en secondes pour évaluer la métrique de mise à l'échelle.",
208+
"TypeMetricNameToDelete": "Saisissez \"{{ metricName }}\" pour confirmer la suppression",
208209
"Upper": "Supérieur"
209210
},
210211
"button": {

0 commit comments

Comments
 (0)