|
@@ -68,10 +68,14 @@ export default function BalancerFormModal({
|
|
|
}: BalancerFormModalProps) {
|
|
}: BalancerFormModalProps) {
|
|
|
const { t } = useTranslation();
|
|
const { t } = useTranslation();
|
|
|
const [state, setState] = useState<FormState>(() => initialState(balancer));
|
|
const [state, setState] = useState<FormState>(() => initialState(balancer));
|
|
|
|
|
+ const [touched, setTouched] = useState<Partial<Record<keyof FormState, boolean>>>({});
|
|
|
|
|
+ const [submitAttempted, setSubmitAttempted] = useState(false);
|
|
|
const isEdit = balancer != null;
|
|
const isEdit = balancer != null;
|
|
|
|
|
|
|
|
- const update = <K extends keyof FormState>(key: K, value: FormState[K]) =>
|
|
|
|
|
|
|
+ const update = <K extends keyof FormState>(key: K, value: FormState[K]) => {
|
|
|
|
|
+ setTouched((prev) => (prev[key] ? prev : { ...prev, [key]: true }));
|
|
|
setState((prev) => ({ ...prev, [key]: value }));
|
|
setState((prev) => ({ ...prev, [key]: value }));
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
const parsed = useMemo(
|
|
const parsed = useMemo(
|
|
|
() => BalancerFormSchema.safeParse(state),
|
|
() => BalancerFormSchema.safeParse(state),
|
|
@@ -89,8 +93,17 @@ export default function BalancerFormModal({
|
|
|
return map;
|
|
return map;
|
|
|
}, [parsed, t]);
|
|
}, [parsed, t]);
|
|
|
|
|
|
|
|
|
|
+ const showTagIssue = submitAttempted || !!touched.tag;
|
|
|
|
|
+ const showSelectorIssue = submitAttempted || !!touched.selector;
|
|
|
|
|
+ const tagError = showTagIssue ? issues.tag : '';
|
|
|
|
|
+ const selectorError = showSelectorIssue ? issues.selector : '';
|
|
|
|
|
+ const showDuplicate = showTagIssue && duplicateTag;
|
|
|
|
|
+
|
|
|
function submit() {
|
|
function submit() {
|
|
|
- if (!parsed.success || duplicateTag) return;
|
|
|
|
|
|
|
+ if (!parsed.success || duplicateTag) {
|
|
|
|
|
+ setSubmitAttempted(true);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
const values = { ...parsed.data };
|
|
const values = { ...parsed.data };
|
|
|
if (values.strategy !== 'leastLoad') delete values.settings;
|
|
if (values.strategy !== 'leastLoad') delete values.settings;
|
|
|
onConfirm(values);
|
|
onConfirm(values);
|
|
@@ -128,7 +141,6 @@ export default function BalancerFormModal({
|
|
|
title={title}
|
|
title={title}
|
|
|
okText={okText}
|
|
okText={okText}
|
|
|
cancelText={t('close')}
|
|
cancelText={t('close')}
|
|
|
- okButtonProps={{ disabled: !parsed.success || duplicateTag }}
|
|
|
|
|
mask={{ closable: false }}
|
|
mask={{ closable: false }}
|
|
|
onOk={submit}
|
|
onOk={submit}
|
|
|
onCancel={onClose}
|
|
onCancel={onClose}
|
|
@@ -137,8 +149,8 @@ export default function BalancerFormModal({
|
|
|
<Form.Item
|
|
<Form.Item
|
|
|
label={t('pages.xray.balancer.tag')}
|
|
label={t('pages.xray.balancer.tag')}
|
|
|
required
|
|
required
|
|
|
- validateStatus={issues.tag ? 'error' : duplicateTag ? 'warning' : ''}
|
|
|
|
|
- help={issues.tag || (duplicateTag ? t('pages.xray.balancer.tagDuplicate') : '')}
|
|
|
|
|
|
|
+ validateStatus={tagError ? 'error' : showDuplicate ? 'warning' : ''}
|
|
|
|
|
+ help={tagError || (showDuplicate ? t('pages.xray.balancer.tagDuplicate') : '')}
|
|
|
hasFeedback
|
|
hasFeedback
|
|
|
>
|
|
>
|
|
|
<Input
|
|
<Input
|
|
@@ -157,8 +169,8 @@ export default function BalancerFormModal({
|
|
|
<Form.Item
|
|
<Form.Item
|
|
|
label={t('pages.xray.balancer.selector')}
|
|
label={t('pages.xray.balancer.selector')}
|
|
|
required
|
|
required
|
|
|
- validateStatus={issues.selector ? 'error' : ''}
|
|
|
|
|
- help={issues.selector || ''}
|
|
|
|
|
|
|
+ validateStatus={selectorError ? 'error' : ''}
|
|
|
|
|
+ help={selectorError || ''}
|
|
|
hasFeedback
|
|
hasFeedback
|
|
|
>
|
|
>
|
|
|
<Select
|
|
<Select
|