refactor(ui): MultipleSplitValueInput

This commit is contained in:
Fu Diwei
2025-05-25 23:05:08 +08:00
parent 71c093c042
commit b798b824db
8 changed files with 178 additions and 501 deletions

View File

@@ -1,12 +1,7 @@
import { forwardRef, memo, useEffect, useImperativeHandle, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { Link } from "react-router";
import {
FormOutlined as FormOutlinedIcon,
PlusOutlined as PlusOutlinedIcon,
QuestionCircleOutlined as QuestionCircleOutlinedIcon,
RightOutlined as RightOutlinedIcon,
} from "@ant-design/icons";
import { PlusOutlined as PlusOutlinedIcon, QuestionCircleOutlined as QuestionCircleOutlinedIcon, RightOutlined as RightOutlinedIcon } from "@ant-design/icons";
import { useControllableValue } from "ahooks";
import {
AutoComplete,
@@ -19,7 +14,6 @@ import {
Input,
InputNumber,
Select,
Space,
Switch,
Tooltip,
Typography,
@@ -29,8 +23,7 @@ import { z } from "zod";
import AccessEditModal from "@/components/access/AccessEditModal";
import AccessSelect from "@/components/access/AccessSelect";
import ModalForm from "@/components/ModalForm";
import MultipleInput from "@/components/MultipleInput";
import MultipleSplitValueInput from "@/components/MultipleSplitValueInput";
import ACMEDns01ProviderSelect from "@/components/provider/ACMEDns01ProviderSelect";
import CAProviderSelect from "@/components/provider/CAProviderSelect";
import Show from "@/components/Show";
@@ -152,11 +145,9 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
initialValues: initialValues ?? initFormModel(),
});
const fieldDomains = Form.useWatch<string>("domains", formInst);
const fieldProvider = Form.useWatch<string>("provider", { form: formInst, preserve: true });
const fieldProviderAccessId = Form.useWatch<string>("providerAccessId", formInst);
const fieldCAProvider = Form.useWatch<string>("caProvider", formInst);
const fieldNameservers = Form.useWatch<string>("nameservers", formInst);
const [showProvider, setShowProvider] = useState(false);
useEffect(() => {
@@ -294,25 +285,17 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
<Form.Provider onFormChange={handleFormProviderChange}>
<Form className={className} style={style} {...formProps} disabled={disabled} layout="vertical" scrollToFirstError onValuesChange={handleFormChange}>
<Form.Item
name="domains"
label={t("workflow_node.apply.form.domains.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.apply.form.domains.tooltip") }}></span>}
>
<Space.Compact style={{ width: "100%" }}>
<Form.Item name="domains" noStyle rules={[formRule]}>
<Input placeholder={t("workflow_node.apply.form.domains.placeholder")} />
</Form.Item>
<DomainsModalInput
value={fieldDomains}
trigger={
<Button disabled={disabled}>
<FormOutlinedIcon />
</Button>
}
onChange={(v) => {
formInst.setFieldValue("domains", v);
}}
/>
</Space.Compact>
<MultipleSplitValueInput
modalTitle={t("workflow_node.apply.form.domains.multiple_input_modal.title")}
placeholder={t("workflow_node.apply.form.domains.placeholder")}
placeholderInModal={t("workflow_node.apply.form.domains.multiple_input_modal.placeholder")}
splitOptions={{ trim: true, removeEmpty: true }}
/>
</Form.Item>
<Form.Item
@@ -497,36 +480,17 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
<Form className={className} style={style} {...formProps} disabled={disabled} layout="vertical" scrollToFirstError onValuesChange={handleFormChange}>
<Form.Item
name="nameservers"
label={t("workflow_node.apply.form.nameservers.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.apply.form.nameservers.tooltip") }}></span>}
>
<Space.Compact style={{ width: "100%" }}>
<Form.Item name="nameservers" noStyle rules={[formRule]}>
<Input
allowClear
disabled={disabled}
value={fieldNameservers}
placeholder={t("workflow_node.apply.form.nameservers.placeholder")}
onChange={(e) => {
formInst.setFieldValue("nameservers", e.target.value);
}}
onClear={() => {
formInst.setFieldValue("nameservers", undefined);
}}
/>
</Form.Item>
<NameserversModalInput
value={fieldNameservers}
trigger={
<Button disabled={disabled}>
<FormOutlinedIcon />
</Button>
}
onChange={(value) => {
formInst.setFieldValue("nameservers", value);
}}
/>
</Space.Compact>
<MultipleSplitValueInput
modalTitle={t("workflow_node.apply.form.nameservers.multiple_input_modal.title")}
placeholder={t("workflow_node.apply.form.nameservers.placeholder")}
placeholderInModal={t("workflow_node.apply.form.nameservers.multiple_input_modal.placeholder")}
splitOptions={{ trim: true, removeEmpty: true }}
/>
</Form.Item>
<Form.Item
@@ -678,84 +642,4 @@ const EmailInput = memo(
}
);
const DomainsModalInput = memo(({ value, trigger, onChange }: { value?: string; trigger?: React.ReactNode; onChange?: (value: string) => void }) => {
const { t } = useTranslation();
const formSchema = z.object({
domains: z.array(z.string()).refine((v) => {
return v.every((e) => !e?.trim() || validDomainName(e.trim(), { allowWildcard: true }));
}, t("common.errmsg.domain_invalid")),
});
const formRule = createSchemaFieldRule(formSchema);
const { form: formInst, formProps } = useAntdForm({
name: "workflowNodeApplyConfigFormDomainsModalInput",
initialValues: { domains: value?.split(MULTIPLE_INPUT_DELIMITER) },
onSubmit: (values) => {
onChange?.(
values.domains
.map((e) => e.trim())
.filter((e) => !!e)
.join(MULTIPLE_INPUT_DELIMITER)
);
},
});
return (
<ModalForm
{...formProps}
layout="vertical"
form={formInst}
modalProps={{ destroyOnHidden: true }}
title={t("workflow_node.apply.form.domains.multiple_input_modal.title")}
trigger={trigger}
validateTrigger="onSubmit"
width={480}
>
<Form.Item name="domains" rules={[formRule]}>
<MultipleInput placeholder={t("workflow_node.apply.form.domains.multiple_input_modal.placeholder")} />
</Form.Item>
</ModalForm>
);
});
const NameserversModalInput = memo(({ trigger, value, onChange }: { trigger?: React.ReactNode; value?: string; onChange?: (value: string) => void }) => {
const { t } = useTranslation();
const formSchema = z.object({
nameservers: z.array(z.string()).refine((v) => {
return v.every((e) => !e?.trim() || validIPv4Address(e) || validIPv6Address(e) || validDomainName(e));
}, t("common.errmsg.domain_invalid")),
});
const formRule = createSchemaFieldRule(formSchema);
const { form: formInst, formProps } = useAntdForm({
name: "workflowNodeApplyConfigFormNameserversModalInput",
initialValues: { nameservers: value?.split(MULTIPLE_INPUT_DELIMITER) },
onSubmit: (values) => {
onChange?.(
values.nameservers
.map((e) => e.trim())
.filter((e) => !!e)
.join(MULTIPLE_INPUT_DELIMITER)
);
},
});
return (
<ModalForm
{...formProps}
layout="vertical"
form={formInst}
modalProps={{ destroyOnHidden: true }}
title={t("workflow_node.apply.form.nameservers.multiple_input_modal.title")}
trigger={trigger}
validateTrigger="onSubmit"
width={480}
>
<Form.Item name="nameservers" rules={[formRule]}>
<MultipleInput placeholder={t("workflow_node.apply.form.nameservers.multiple_input_modal.placeholder")} />
</Form.Item>
</ModalForm>
);
});
export default memo(ApplyNodeConfigForm);

View File

@@ -1,13 +1,9 @@
import { memo } from "react";
import { useTranslation } from "react-i18next";
import { FormOutlined as FormOutlinedIcon } from "@ant-design/icons";
import { Alert, Button, Form, type FormInstance, Input, Space } from "antd";
import { Alert, Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import ModalForm from "@/components/ModalForm";
import MultipleInput from "@/components/MultipleInput";
import { useAntdForm } from "@/hooks";
import MultipleSplitValueInput from "@/components/MultipleSplitValueInput";
type DeployNodeConfigFormAliyunCASDeployConfigFieldValues = Nullish<{
region: string;
@@ -61,9 +57,6 @@ const DeployNodeConfigFormAliyunCASDeployConfig = ({
});
const formRule = createSchemaFieldRule(formSchema);
const fieldResourceIds = Form.useWatch<string>("resourceIds", formInst);
const fieldContactIds = Form.useWatch<string>("contactIds", formInst);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
};
@@ -87,69 +80,31 @@ const DeployNodeConfigFormAliyunCASDeployConfig = ({
</Form.Item>
<Form.Item
name="resourceIds"
label={t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.tooltip") }}></span>}
>
<Space.Compact style={{ width: "100%" }}>
<Form.Item name="resourceIds" noStyle rules={[formRule]}>
<Input
allowClear
disabled={disabled}
value={fieldResourceIds}
placeholder={t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.placeholder")}
onChange={(e) => {
formInst.setFieldValue("resourceIds", e.target.value);
}}
onClear={() => {
formInst.setFieldValue("resourceIds", "");
}}
/>
</Form.Item>
<ResourceIdsModalInput
value={fieldResourceIds}
trigger={
<Button disabled={disabled}>
<FormOutlinedIcon />
</Button>
}
onChange={(value) => {
formInst.setFieldValue("resourceIds", value);
}}
/>
</Space.Compact>
<MultipleSplitValueInput
modalTitle={t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.multiple_input_modal.title")}
placeholder={t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.placeholder")}
placeholderInModal={t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.multiple_input_modal.placeholder")}
splitOptions={{ trim: true, removeEmpty: true }}
/>
</Form.Item>
<Form.Item
name="contactIds"
label={t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.tooltip") }}></span>}
>
<Space.Compact style={{ width: "100%" }}>
<Form.Item name="contactIds" noStyle rules={[formRule]}>
<Input
allowClear
disabled={disabled}
value={fieldContactIds}
placeholder={t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.placeholder")}
onChange={(e) => {
formInst.setFieldValue("contactIds", e.target.value);
}}
onClear={() => {
formInst.setFieldValue("contactIds", "");
}}
/>
</Form.Item>
<ContactIdsModalInput
value={fieldContactIds}
trigger={
<Button disabled={disabled}>
<FormOutlinedIcon />
</Button>
}
onChange={(value) => {
formInst.setFieldValue("contactIds", value);
}}
/>
</Space.Compact>
<MultipleSplitValueInput
modalTitle={t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.multiple_input_modal.title")}
placeholder={t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.placeholder")}
placeholderInModal={t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.multiple_input_modal.placeholder")}
splitOptions={{ trim: true, removeEmpty: true }}
/>
</Form.Item>
<Form.Item>
@@ -159,84 +114,4 @@ const DeployNodeConfigFormAliyunCASDeployConfig = ({
);
};
const ResourceIdsModalInput = memo(({ value, trigger, onChange }: { value?: string; trigger?: React.ReactNode; onChange?: (value: string) => void }) => {
const { t } = useTranslation();
const formSchema = z.object({
resourceIds: z.array(z.string()).refine((v) => {
return v.every((e) => !e?.trim() || /^[1-9]\d*$/.test(e));
}, t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.errmsg.invalid")),
});
const formRule = createSchemaFieldRule(formSchema);
const { form: formInst, formProps } = useAntdForm({
name: "workflowNodeDeployConfigFormAliyunCASResourceIdsModalInput",
initialValues: { resourceIds: value?.split(MULTIPLE_INPUT_DELIMITER) },
onSubmit: (values) => {
onChange?.(
values.resourceIds
.map((e) => e.trim())
.filter((e) => !!e)
.join(MULTIPLE_INPUT_DELIMITER)
);
},
});
return (
<ModalForm
{...formProps}
layout="vertical"
form={formInst}
modalProps={{ destroyOnHidden: true }}
title={t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.multiple_input_modal.title")}
trigger={trigger}
validateTrigger="onSubmit"
width={480}
>
<Form.Item name="resourceIds" rules={[formRule]}>
<MultipleInput placeholder={t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.multiple_input_modal.placeholder")} />
</Form.Item>
</ModalForm>
);
});
const ContactIdsModalInput = memo(({ value, trigger, onChange }: { value?: string; trigger?: React.ReactNode; onChange?: (value: string) => void }) => {
const { t } = useTranslation();
const formSchema = z.object({
contactIds: z.array(z.string()).refine((v) => {
return v.every((e) => !e?.trim() || /^[1-9]\d*$/.test(e));
}, t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.errmsg.invalid")),
});
const formRule = createSchemaFieldRule(formSchema);
const { form: formInst, formProps } = useAntdForm({
name: "workflowNodeDeployConfigFormAliyunCASDeploymentJobContactIdsModalInput",
initialValues: { contactIds: value?.split(MULTIPLE_INPUT_DELIMITER) },
onSubmit: (values) => {
onChange?.(
values.contactIds
.map((e) => e.trim())
.filter((e) => !!e)
.join(MULTIPLE_INPUT_DELIMITER)
);
},
});
return (
<ModalForm
{...formProps}
layout="vertical"
form={formInst}
modalProps={{ destroyOnHidden: true }}
title={t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.multiple_input_modal.title")}
trigger={trigger}
validateTrigger="onSubmit"
width={480}
>
<Form.Item name="contactIds" rules={[formRule]}>
<MultipleInput placeholder={t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.multiple_input_modal.placeholder")} />
</Form.Item>
</ModalForm>
);
});
export default DeployNodeConfigFormAliyunCASDeployConfig;

View File

@@ -1,14 +1,10 @@
import { memo } from "react";
import { useTranslation } from "react-i18next";
import { FormOutlined as FormOutlinedIcon } from "@ant-design/icons";
import { Button, Form, type FormInstance, Input, Select, Space } from "antd";
import { Form, type FormInstance, Input, Select } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import ModalForm from "@/components/ModalForm";
import MultipleInput from "@/components/MultipleInput";
import MultipleSplitValueInput from "@/components/MultipleSplitValueInput";
import Show from "@/components/Show";
import { useAntdForm } from "@/hooks";
type DeployNodeConfigFormBaotaPanelSiteConfigFieldValues = Nullish<{
siteType: string;
@@ -71,7 +67,6 @@ const DeployNodeConfigFormBaotaPanelSiteConfig = ({
const formRule = createSchemaFieldRule(formSchema);
const fieldSiteType = Form.useWatch<string>("siteType", formInst);
const fieldSiteNames = Form.useWatch<string>("siteNames", formInst);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
@@ -110,80 +105,21 @@ const DeployNodeConfigFormBaotaPanelSiteConfig = ({
<Show when={fieldSiteType === SITE_TYPE_OTHER}>
<Form.Item
name="siteNames"
label={t("workflow_node.deploy.form.baotapanel_site_names.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.baotapanel_site_names.tooltip") }}></span>}
>
<Space.Compact style={{ width: "100%" }}>
<Form.Item name="siteNames" noStyle rules={[formRule]}>
<Input
allowClear
disabled={disabled}
value={fieldSiteNames}
placeholder={t("workflow_node.deploy.form.baotapanel_site_names.placeholder")}
onChange={(e) => {
formInst.setFieldValue("siteNames", e.target.value);
}}
onClear={() => {
formInst.setFieldValue("siteNames", "");
}}
/>
</Form.Item>
<SiteNamesModalInput
value={fieldSiteNames}
trigger={
<Button disabled={disabled}>
<FormOutlinedIcon />
</Button>
}
onChange={(value) => {
formInst.setFieldValue("siteNames", value);
}}
/>
</Space.Compact>
<MultipleSplitValueInput
modalTitle={t("workflow_node.deploy.form.baotapanel_site_names.multiple_input_modal.title")}
placeholder={t("workflow_node.deploy.form.baotapanel_site_names.placeholder")}
placeholderInModal={t("workflow_node.deploy.form.baotapanel_site_names.multiple_input_modal.placeholder")}
splitOptions={{ trim: true, removeEmpty: true }}
/>
</Form.Item>
</Show>
</Form>
);
};
const SiteNamesModalInput = memo(({ value, trigger, onChange }: { value?: string; trigger?: React.ReactNode; onChange?: (value: string) => void }) => {
const { t } = useTranslation();
const formSchema = z.object({
siteNames: z.array(z.string()).refine((v) => {
return v.every((e) => !!e?.trim());
}, t("workflow_node.deploy.form.baotapanel_site_names.errmsg.invalid")),
});
const formRule = createSchemaFieldRule(formSchema);
const { form: formInst, formProps } = useAntdForm({
name: "workflowNodeDeployConfigFormBaotaPanelSiteNamesModalInput",
initialValues: { siteNames: value?.split(MULTIPLE_INPUT_DELIMITER) },
onSubmit: (values) => {
onChange?.(
values.siteNames
.map((e) => e.trim())
.filter((e) => !!e)
.join(MULTIPLE_INPUT_DELIMITER)
);
},
});
return (
<ModalForm
{...formProps}
layout="vertical"
form={formInst}
modalProps={{ destroyOnHidden: true }}
title={t("workflow_node.deploy.form.baotapanel_site_names.multiple_input_modal.title")}
trigger={trigger}
validateTrigger="onSubmit"
width={480}
>
<Form.Item name="siteNames" rules={[formRule]}>
<MultipleInput placeholder={t("workflow_node.deploy.form.baotapanel_site_names.multiple_input_modal.placeholder")} />
</Form.Item>
</ModalForm>
);
});
export default DeployNodeConfigFormBaotaPanelSiteConfig;

View File

@@ -1,13 +1,9 @@
import { memo } from "react";
import { useTranslation } from "react-i18next";
import { FormOutlined as FormOutlinedIcon } from "@ant-design/icons";
import { Alert, AutoComplete, Button, Form, type FormInstance, Input, Space } from "antd";
import { Alert, AutoComplete, Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import ModalForm from "@/components/ModalForm";
import MultipleInput from "@/components/MultipleInput";
import { useAntdForm } from "@/hooks";
import MultipleSplitValueInput from "@/components/MultipleSplitValueInput";
type DeployNodeConfigFormTencentCloudSSLDeployConfigFieldValues = Nullish<{
region: string;
@@ -56,8 +52,6 @@ const DeployNodeConfigFormTencentCloudSSLDeployConfig = ({
});
const formRule = createSchemaFieldRule(formSchema);
const fieldResourceIds = Form.useWatch<string>("resourceIds", formInst);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
};
@@ -94,36 +88,17 @@ const DeployNodeConfigFormTencentCloudSSLDeployConfig = ({
</Form.Item>
<Form.Item
name="resourceIds"
label={t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.tooltip") }}></span>}
>
<Space.Compact style={{ width: "100%" }}>
<Form.Item name="resourceIds" noStyle rules={[formRule]}>
<Input
allowClear
disabled={disabled}
value={fieldResourceIds}
placeholder={t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.placeholder")}
onChange={(e) => {
formInst.setFieldValue("resourceIds", e.target.value);
}}
onClear={() => {
formInst.setFieldValue("resourceIds", "");
}}
/>
</Form.Item>
<ResourceIdsModalInput
value={fieldResourceIds}
trigger={
<Button disabled={disabled}>
<FormOutlinedIcon />
</Button>
}
onChange={(value) => {
formInst.setFieldValue("resourceIds", value);
}}
/>
</Space.Compact>
<MultipleSplitValueInput
modalTitle={t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.title")}
placeholder={t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.placeholder")}
placeholderInModal={t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.placeholder")}
splitOptions={{ trim: true, removeEmpty: true }}
/>
</Form.Item>
<Form.Item>
@@ -133,44 +108,4 @@ const DeployNodeConfigFormTencentCloudSSLDeployConfig = ({
);
};
const ResourceIdsModalInput = memo(({ value, trigger, onChange }: { value?: string; trigger?: React.ReactNode; onChange?: (value: string) => void }) => {
const { t } = useTranslation();
const formSchema = z.object({
resourceIds: z.array(z.string()).refine((v) => {
return v.every((e) => !e?.trim() || /^[A-Za-z0-9*._-|]+$/.test(e));
}, t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.errmsg.invalid")),
});
const formRule = createSchemaFieldRule(formSchema);
const { form: formInst, formProps } = useAntdForm({
name: "workflowNodeDeployConfigFormTencentCloudSSLDeployResourceIdsModalInput",
initialValues: { resourceIds: value?.split(MULTIPLE_INPUT_DELIMITER) },
onSubmit: (values) => {
onChange?.(
values.resourceIds
.map((e) => e.trim())
.filter((e) => !!e)
.join(MULTIPLE_INPUT_DELIMITER)
);
},
});
return (
<ModalForm
{...formProps}
layout="vertical"
form={formInst}
modalProps={{ destroyOnHidden: true }}
title={t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.title")}
trigger={trigger}
validateTrigger="onSubmit"
width={480}
>
<Form.Item name="resourceIds" rules={[formRule]}>
<MultipleInput placeholder={t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.placeholder")} />
</Form.Item>
</ModalForm>
);
});
export default DeployNodeConfigFormTencentCloudSSLDeployConfig;

View File

@@ -1,13 +1,9 @@
import { memo } from "react";
import { useTranslation } from "react-i18next";
import { FormOutlined as FormOutlinedIcon } from "@ant-design/icons";
import { Button, Form, type FormInstance, Input, Space } from "antd";
import { Form, type FormInstance } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import ModalForm from "@/components/ModalForm";
import MultipleInput from "@/components/MultipleInput";
import { useAntdForm } from "@/hooks";
import MultipleSplitValueInput from "@/components/MultipleSplitValueInput";
import { validDomainName } from "@/utils/validators";
type DeployNodeConfigFormWangsuCDNConfigFieldValues = Nullish<{
@@ -52,8 +48,6 @@ const DeployNodeConfigFormWangsuCDNConfig = ({
});
const formRule = createSchemaFieldRule(formSchema);
const fieldDomains = Form.useWatch<string>("domains", formInst);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
};
@@ -68,79 +62,20 @@ const DeployNodeConfigFormWangsuCDNConfig = ({
onValuesChange={handleFormChange}
>
<Form.Item
name="domains"
label={t("workflow_node.deploy.form.wangsu_cdn_domains.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.wangsu_cdn_domains.tooltip") }}></span>}
>
<Space.Compact style={{ width: "100%" }}>
<Form.Item name="domains" noStyle rules={[formRule]}>
<Input
allowClear
disabled={disabled}
value={fieldDomains}
placeholder={t("workflow_node.deploy.form.wangsu_cdn_domains.placeholder")}
onChange={(e) => {
formInst.setFieldValue("domains", e.target.value);
}}
onClear={() => {
formInst.setFieldValue("domains", "");
}}
/>
</Form.Item>
<SiteNamesModalInput
value={fieldDomains}
trigger={
<Button disabled={disabled}>
<FormOutlinedIcon />
</Button>
}
onChange={(value) => {
formInst.setFieldValue("domains", value);
}}
/>
</Space.Compact>
<MultipleSplitValueInput
modalTitle={t("workflow_node.deploy.form.wangsu_cdn_domains.multiple_input_modal.title")}
placeholder={t("workflow_node.deploy.form.wangsu_cdn_domains.placeholder")}
placeholderInModal={t("workflow_node.deploy.form.wangsu_cdn_domains.multiple_input_modal.placeholder")}
splitOptions={{ trim: true, removeEmpty: true }}
/>
</Form.Item>
</Form>
);
};
const SiteNamesModalInput = memo(({ value, trigger, onChange }: { value?: string; trigger?: React.ReactNode; onChange?: (value: string) => void }) => {
const { t } = useTranslation();
const formSchema = z.object({
domains: z.array(z.string()).refine((v) => {
return v.every((e) => validDomainName(e));
}, t("workflow_node.deploy.form.wangsu_cdn_domains.errmsg.invalid")),
});
const formRule = createSchemaFieldRule(formSchema);
const { form: formInst, formProps } = useAntdForm({
name: "workflowNodeDeployConfigFormWangsuCDNNamesModalInput",
initialValues: { domains: value?.split(MULTIPLE_INPUT_DELIMITER) },
onSubmit: (values) => {
onChange?.(
values.domains
.map((e) => e.trim())
.filter((e) => !!e)
.join(MULTIPLE_INPUT_DELIMITER)
);
},
});
return (
<ModalForm
{...formProps}
layout="vertical"
form={formInst}
modalProps={{ destroyOnHidden: true }}
title={t("workflow_node.deploy.form.wangsu_cdn_domains.multiple_input_modal.title")}
trigger={trigger}
validateTrigger="onSubmit"
width={480}
>
<Form.Item name="domains" rules={[formRule]}>
<MultipleInput placeholder={t("workflow_node.deploy.form.wangsu_cdn_domains.multiple_input_modal.placeholder")} />
</Form.Item>
</ModalForm>
);
});
export default DeployNodeConfigFormWangsuCDNConfig;