Merge branch 'main' into feat-ssh-jumpserver

This commit is contained in:
RHQYZ
2025-05-20 21:42:38 +08:00
committed by GitHub
163 changed files with 5497 additions and 945 deletions

View File

@@ -12,6 +12,7 @@ import { ACCESS_PROVIDERS, ACCESS_USAGES, type AccessProvider } from "@/domain/p
import { useAntdForm, useAntdFormName } from "@/hooks";
import AccessForm1PanelConfig from "./AccessForm1PanelConfig";
import AccessFormACMECAConfig from "./AccessFormACMECAConfig";
import AccessFormACMEHttpReqConfig from "./AccessFormACMEHttpReqConfig";
import AccessFormAliyunConfig from "./AccessFormAliyunConfig";
import AccessFormAWSConfig from "./AccessFormAWSConfig";
@@ -19,6 +20,7 @@ import AccessFormAzureConfig from "./AccessFormAzureConfig";
import AccessFormBaiduCloudConfig from "./AccessFormBaiduCloudConfig";
import AccessFormBaishanConfig from "./AccessFormBaishanConfig";
import AccessFormBaotaPanelConfig from "./AccessFormBaotaPanelConfig";
import AccessFormBaotaWAFConfig from "./AccessFormBaotaWAFConfig";
import AccessFormBunnyConfig from "./AccessFormBunnyConfig";
import AccessFormBytePlusConfig from "./AccessFormBytePlusConfig";
import AccessFormCacheFlyConfig from "./AccessFormCacheFlyConfig";
@@ -33,6 +35,7 @@ import AccessFormDogeCloudConfig from "./AccessFormDogeCloudConfig";
import AccessFormDynv6Config from "./AccessFormDynv6Config";
import AccessFormEdgioConfig from "./AccessFormEdgioConfig";
import AccessFormEmailConfig from "./AccessFormEmailConfig";
import AccessFormFlexCDNConfig from "./AccessFormFlexCDNConfig";
import AccessFormGcoreConfig from "./AccessFormGcoreConfig";
import AccessFormGnameConfig from "./AccessFormGnameConfig";
import AccessFormGoDaddyConfig from "./AccessFormGoDaddyConfig";
@@ -42,6 +45,7 @@ import AccessFormHuaweiCloudConfig from "./AccessFormHuaweiCloudConfig";
import AccessFormJDCloudConfig from "./AccessFormJDCloudConfig";
import AccessFormKubernetesConfig from "./AccessFormKubernetesConfig";
import AccessFormLarkBotConfig from "./AccessFormLarkBotConfig";
import AccessFormLeCDNConfig from "./AccessFormLeCDNConfig";
import AccessFormMattermostConfig from "./AccessFormMattermostConfig";
import AccessFormNamecheapConfig from "./AccessFormNamecheapConfig";
import AccessFormNameDotComConfig from "./AccessFormNameDotComConfig";
@@ -54,6 +58,7 @@ import AccessFormPowerDNSConfig from "./AccessFormPowerDNSConfig";
import AccessFormProxmoxVEConfig from "./AccessFormProxmoxVEConfig";
import AccessFormQiniuConfig from "./AccessFormQiniuConfig";
import AccessFormRainYunConfig from "./AccessFormRainYunConfig";
import AccessFormRatPanelConfig from "./AccessFormRatPanelConfig";
import AccessFormSafeLineConfig from "./AccessFormSafeLineConfig";
import AccessFormSSHConfig from "./AccessFormSSHConfig";
import AccessFormSSLComConfig from "./AccessFormSSLComConfig";
@@ -176,6 +181,8 @@ const AccessForm = forwardRef<AccessFormInstance, AccessFormProps>(({ className,
switch (fieldProvider) {
case ACCESS_PROVIDERS["1PANEL"]:
return <AccessForm1PanelConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.ACMECA:
return <AccessFormACMECAConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.ACMEHTTPREQ:
return <AccessFormACMEHttpReqConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.ALIYUN:
@@ -190,6 +197,8 @@ const AccessForm = forwardRef<AccessFormInstance, AccessFormProps>(({ className,
return <AccessFormBaishanConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.BAOTAPANEL:
return <AccessFormBaotaPanelConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.BAOTAWAF:
return <AccessFormBaotaWAFConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.BUNNY:
return <AccessFormBunnyConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.BYTEPLUS:
@@ -214,6 +223,12 @@ const AccessForm = forwardRef<AccessFormInstance, AccessFormProps>(({ className,
return <AccessFormDogeCloudConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.DYNV6:
return <AccessFormDynv6Config {...nestedFormProps} />;
case ACCESS_PROVIDERS.EDGIO:
return <AccessFormEdgioConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.EMAIL:
return <AccessFormEmailConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.FLEXCDN:
return <AccessFormFlexCDNConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.GCORE:
return <AccessFormGcoreConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.GNAME:
@@ -224,10 +239,6 @@ const AccessForm = forwardRef<AccessFormInstance, AccessFormProps>(({ className,
return <AccessFormGoEdgeConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.GOOGLETRUSTSERVICES:
return <AccessFormGoogleTrustServicesConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.EDGIO:
return <AccessFormEdgioConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.EMAIL:
return <AccessFormEmailConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.HUAWEICLOUD:
return <AccessFormHuaweiCloudConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.JDCLOUD:
@@ -236,6 +247,8 @@ const AccessForm = forwardRef<AccessFormInstance, AccessFormProps>(({ className,
return <AccessFormKubernetesConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.LARKBOT:
return <AccessFormLarkBotConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.LECDN:
return <AccessFormLeCDNConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.MATTERMOST:
return <AccessFormMattermostConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.NAMECHEAP:
@@ -260,6 +273,8 @@ const AccessForm = forwardRef<AccessFormInstance, AccessFormProps>(({ className,
return <AccessFormQiniuConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.RAINYUN:
return <AccessFormRainYunConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.RATPANEL:
return <AccessFormRatPanelConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.SAFELINE:
return <AccessFormSafeLineConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.SSH:

View File

@@ -1,5 +1,5 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Switch } from "antd";
import { Form, type FormInstance, Input, Select, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
@@ -18,6 +18,7 @@ export type AccessForm1PanelConfigProps = {
const initFormModel = (): AccessForm1PanelConfigFieldValues => {
return {
apiUrl: "http://<your-host-addr>:20410/",
apiVersion: "v1",
apiKey: "",
};
};
@@ -27,6 +28,7 @@ const AccessForm1PanelConfig = ({ form: formInst, formName, disabled, initialVal
const formSchema = z.object({
apiUrl: z.string().url(t("common.errmsg.url_invalid")),
apiVersion: z.string().nonempty(t("access.form.1panel_api_version.placeholder")),
apiKey: z
.string()
.min(1, t("access.form.1panel_api_key.placeholder"))
@@ -53,6 +55,10 @@ const AccessForm1PanelConfig = ({ form: formInst, formName, disabled, initialVal
<Input placeholder={t("access.form.1panel_api_url.placeholder")} />
</Form.Item>
<Form.Item name="apiVersion" label={t("access.form.1panel_api_version.label")} rules={[formRule]}>
<Select options={["v1", "v2"].map((s) => ({ label: s, value: s }))} placeholder={t("access.form.1panel_api_version.placeholder")} />
</Form.Item>
<Form.Item
name="apiKey"
label={t("access.form.1panel_api_key.label")}

View File

@@ -0,0 +1,77 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type AccessConfigForACMECA } from "@/domain/access";
type AccessFormACMECAConfigFieldValues = Nullish<AccessConfigForACMECA>;
export type AccessFormACMECAConfigProps = {
form: FormInstance;
formName: string;
disabled?: boolean;
initialValues?: AccessFormACMECAConfigFieldValues;
onValuesChange?: (values: AccessFormACMECAConfigFieldValues) => void;
};
const initFormModel = (): AccessFormACMECAConfigFieldValues => {
return {
endpoint: "https://example.com/acme/directory",
};
};
const AccessFormACMECAConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormACMECAConfigProps) => {
const { t } = useTranslation();
const formSchema = z.object({
endpoint: z.string().url(t("common.errmsg.url_invalid")),
eabKid: z.string().trim().nullish(),
eabHmacKey: z.string().trim().nullish(),
});
const formRule = createSchemaFieldRule(formSchema);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
};
return (
<Form
form={formInst}
disabled={disabled}
initialValues={initialValues ?? initFormModel()}
layout="vertical"
name={formName}
onValuesChange={handleFormChange}
>
<Form.Item
name="endpoint"
label={t("access.form.acmeca_endpoint.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.acmeca_endpoint.tooltip") }}></span>}
>
<Input placeholder={t("access.form.acmeca_endpoint.placeholder")} />
</Form.Item>
<Form.Item
name="eabKid"
label={t("access.form.acmeca_eab_kid.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.acmeca_eab_kid.tooltip") }}></span>}
>
<Input allowClear autoComplete="new-password" placeholder={t("access.form.acmeca_eab_kid.placeholder")} />
</Form.Item>
<Form.Item
name="eabHmacKey"
label={t("access.form.acmeca_eab_hmac_key.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.acmeca_eab_hmac_key.tooltip") }}></span>}
>
<Input.Password allowClear autoComplete="new-password" placeholder={t("access.form.acmeca_eab_hmac_key.placeholder")} />
</Form.Item>
</Form>
);
};
export default AccessFormACMECAConfig;

View File

@@ -84,7 +84,7 @@ const AccessFormACMEHttpReqConfig = ({ form: formInst, formName, disabled, initi
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.acmehttpreq_username.tooltip") }}></span>}
>
<Input autoComplete="new-password" placeholder={t("access.form.acmehttpreq_username.placeholder")} />
<Input allowClear autoComplete="new-password" placeholder={t("access.form.acmehttpreq_username.placeholder")} />
</Form.Item>
<Form.Item
@@ -93,7 +93,7 @@ const AccessFormACMEHttpReqConfig = ({ form: formInst, formName, disabled, initi
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.acmehttpreq_password.tooltip") }}></span>}
>
<Input.Password autoComplete="new-password" placeholder={t("access.form.acmehttpreq_password.placeholder")} />
<Input.Password allowClear autoComplete="new-password" placeholder={t("access.form.acmehttpreq_password.placeholder")} />
</Form.Item>
</Form>
);

View File

@@ -27,11 +27,7 @@ const AccessFormBaotaPanelConfig = ({ form: formInst, formName, disabled, initia
const formSchema = z.object({
apiUrl: z.string().url(t("common.errmsg.url_invalid")),
apiKey: z
.string()
.min(1, t("access.form.baotapanel_api_key.placeholder"))
.max(64, t("common.errmsg.string_max", { max: 64 }))
.trim(),
apiKey: z.string().nonempty(t("access.form.baotapanel_api_key.placeholder")).trim(),
allowInsecureConnections: z.boolean().nullish(),
});
const formRule = createSchemaFieldRule(formSchema);

View File

@@ -0,0 +1,71 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type AccessConfigForBaotaWAF } from "@/domain/access";
type AccessFormBaotaWAFConfigFieldValues = Nullish<AccessConfigForBaotaWAF>;
export type AccessFormBaotaWAFConfigProps = {
form: FormInstance;
formName: string;
disabled?: boolean;
initialValues?: AccessFormBaotaWAFConfigFieldValues;
onValuesChange?: (values: AccessFormBaotaWAFConfigFieldValues) => void;
};
const initFormModel = (): AccessFormBaotaWAFConfigFieldValues => {
return {
apiUrl: "http://<your-host-addr>:8379/",
apiKey: "",
};
};
const AccessFormBaotaWAFConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormBaotaWAFConfigProps) => {
const { t } = useTranslation();
const formSchema = z.object({
apiUrl: z.string().url(t("common.errmsg.url_invalid")),
apiKey: z.string().nonempty(t("access.form.baotawaf_api_key.placeholder")).trim(),
allowInsecureConnections: z.boolean().nullish(),
});
const formRule = createSchemaFieldRule(formSchema);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
};
return (
<Form
form={formInst}
disabled={disabled}
initialValues={initialValues ?? initFormModel()}
layout="vertical"
name={formName}
onValuesChange={handleFormChange}
>
<Form.Item name="apiUrl" label={t("access.form.baotawaf_api_url.label")} rules={[formRule]}>
<Input placeholder={t("access.form.baotawaf_api_url.placeholder")} />
</Form.Item>
<Form.Item
name="apiKey"
label={t("access.form.baotawaf_api_key.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.baotawaf_api_key.tooltip") }}></span>}
>
<Input.Password autoComplete="new-password" placeholder={t("access.form.baotawaf_api_key.placeholder")} />
</Form.Item>
<Form.Item name="allowInsecureConnections" label={t("access.form.baotawaf_allow_insecure_conns.label")} rules={[formRule]}>
<Switch
checkedChildren={t("access.form.baotawaf_allow_insecure_conns.switch.on")}
unCheckedChildren={t("access.form.baotawaf_allow_insecure_conns.switch.off")}
/>
</Form.Item>
</Form>
);
};
export default AccessFormBaotaWAFConfig;

View File

@@ -66,7 +66,7 @@ const AccessFormCloudflareConfig = ({ form: formInst, formName, disabled, initia
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.cloudflare_zone_api_token.tooltip") }}></span>}
>
<Input.Password autoComplete="new-password" placeholder={t("access.form.cloudflare_zone_api_token.placeholder")} />
<Input.Password allowClear autoComplete="new-password" placeholder={t("access.form.cloudflare_zone_api_token.placeholder")} />
</Form.Item>
</Form>
);

View File

@@ -0,0 +1,90 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Radio, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type AccessConfigForFlexCDN } from "@/domain/access";
type AccessFormFlexCDNConfigFieldValues = Nullish<AccessConfigForFlexCDN>;
export type AccessFormFlexCDNConfigProps = {
form: FormInstance;
formName: string;
disabled?: boolean;
initialValues?: AccessFormFlexCDNConfigFieldValues;
onValuesChange?: (values: AccessFormFlexCDNConfigFieldValues) => void;
};
const initFormModel = (): AccessFormFlexCDNConfigFieldValues => {
return {
apiUrl: "http://<your-host-addr>:8000/",
apiRole: "user",
accessKeyId: "",
accessKey: "",
};
};
const AccessFormFlexCDNConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormFlexCDNConfigProps) => {
const { t } = useTranslation();
const formSchema = z.object({
apiUrl: z.string().url(t("common.errmsg.url_invalid")),
role: z.union([z.literal("user"), z.literal("admin")], {
message: t("access.form.flexcdn_api_role.placeholder"),
}),
accessKeyId: z.string().nonempty(t("access.form.flexcdn_access_key_id.placeholder")).trim(),
accessKey: z.string().nonempty(t("access.form.flexcdn_access_key.placeholder")).trim(),
allowInsecureConnections: z.boolean().nullish(),
});
const formRule = createSchemaFieldRule(formSchema);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
};
return (
<Form
form={formInst}
disabled={disabled}
initialValues={initialValues ?? initFormModel()}
layout="vertical"
name={formName}
onValuesChange={handleFormChange}
>
<Form.Item name="apiUrl" label={t("access.form.flexcdn_api_url.label")} rules={[formRule]}>
<Input placeholder={t("access.form.flexcdn_api_url.placeholder")} />
</Form.Item>
<Form.Item name="apiRole" label={t("access.form.flexcdn_api_role.label")} rules={[formRule]}>
<Radio.Group options={["user", "admin"].map((s) => ({ label: t(`access.form.flexcdn_api_role.option.${s}.label`), value: s }))} />
</Form.Item>
<Form.Item
name="accessKeyId"
label={t("access.form.flexcdn_access_key_id.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.flexcdn_access_key_id.tooltip") }}></span>}
>
<Input autoComplete="new-password" placeholder={t("access.form.flexcdn_access_key_id.placeholder")} />
</Form.Item>
<Form.Item
name="accessKey"
label={t("access.form.flexcdn_access_key.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.flexcdn_access_key.tooltip") }}></span>}
>
<Input.Password autoComplete="new-password" placeholder={t("access.form.flexcdn_access_key.placeholder")} />
</Form.Item>
<Form.Item name="allowInsecureConnections" label={t("access.form.flexcdn_allow_insecure_conns.label")} rules={[formRule]}>
<Switch
checkedChildren={t("access.form.flexcdn_allow_insecure_conns.switch.on")}
unCheckedChildren={t("access.form.flexcdn_allow_insecure_conns.switch.off")}
/>
</Form.Item>
</Form>
);
};
export default AccessFormFlexCDNConfig;

View File

@@ -32,16 +32,8 @@ const AccessFormGoEdgeConfig = ({ form: formInst, formName, disabled, initialVal
role: z.union([z.literal("user"), z.literal("admin")], {
message: t("access.form.goedge_api_role.placeholder"),
}),
accessKeyId: z
.string()
.min(1, t("access.form.goedge_access_key_id.placeholder"))
.max(64, t("common.errmsg.string_max", { max: 64 }))
.trim(),
accessKey: z
.string()
.min(1, t("access.form.goedge_access_key.placeholder"))
.max(64, t("common.errmsg.string_max", { max: 64 }))
.trim(),
accessKeyId: z.string().nonempty(t("access.form.goedge_access_key_id.placeholder")).trim(),
accessKey: z.string().nonempty(t("access.form.goedge_access_key.placeholder")).trim(),
allowInsecureConnections: z.boolean().nullish(),
});
const formRule = createSchemaFieldRule(formSchema);

View File

@@ -0,0 +1,85 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Radio, Select, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type AccessConfigForLeCDN } from "@/domain/access";
type AccessFormLeCDNConfigFieldValues = Nullish<AccessConfigForLeCDN>;
export type AccessFormLeCDNConfigProps = {
form: FormInstance;
formName: string;
disabled?: boolean;
initialValues?: AccessFormLeCDNConfigFieldValues;
onValuesChange?: (values: AccessFormLeCDNConfigFieldValues) => void;
};
const initFormModel = (): AccessFormLeCDNConfigFieldValues => {
return {
apiUrl: "http://<your-host-addr>:5090/",
apiVersion: "v3",
apiRole: "user",
username: "",
password: "",
};
};
const AccessFormLeCDNConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormLeCDNConfigProps) => {
const { t } = useTranslation();
const formSchema = z.object({
apiUrl: z.string().url(t("common.errmsg.url_invalid")),
role: z.union([z.literal("client"), z.literal("master")], {
message: t("access.form.lecdn_api_role.placeholder"),
}),
username: z.string().nonempty(t("access.form.lecdn_username.placeholder")).trim(),
password: z.string().nonempty(t("access.form.lecdn_password.placeholder")).trim(),
allowInsecureConnections: z.boolean().nullish(),
});
const formRule = createSchemaFieldRule(formSchema);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
};
return (
<Form
form={formInst}
disabled={disabled}
initialValues={initialValues ?? initFormModel()}
layout="vertical"
name={formName}
onValuesChange={handleFormChange}
>
<Form.Item name="apiUrl" label={t("access.form.lecdn_api_url.label")} rules={[formRule]}>
<Input placeholder={t("access.form.lecdn_api_url.placeholder")} />
</Form.Item>
<Form.Item name="apiVersion" label={t("access.form.lecdn_api_version.label")} rules={[formRule]}>
<Select options={["v3"].map((s) => ({ label: s, value: s }))} placeholder={t("access.form.lecdn_api_version.placeholder")} />
</Form.Item>
<Form.Item name="apiRole" label={t("access.form.lecdn_api_role.label")} rules={[formRule]}>
<Radio.Group options={["user", "master"].map((s) => ({ label: t(`access.form.lecdn_api_role.option.${s}.label`), value: s }))} />
</Form.Item>
<Form.Item name="username" label={t("access.form.lecdn_username.label")} rules={[formRule]}>
<Input autoComplete="new-password" placeholder={t("access.form.lecdn_username.placeholder")} />
</Form.Item>
<Form.Item name="password" label={t("access.form.lecdn_password.label")} rules={[formRule]}>
<Input.Password autoComplete="new-password" placeholder={t("access.form.lecdn_password.placeholder")} />
</Form.Item>
<Form.Item name="allowInsecureConnections" label={t("access.form.lecdn_allow_insecure_conns.label")} rules={[formRule]}>
<Switch
checkedChildren={t("access.form.lecdn_allow_insecure_conns.switch.on")}
unCheckedChildren={t("access.form.lecdn_allow_insecure_conns.switch.off")}
/>
</Form.Item>
</Form>
);
};
export default AccessFormLeCDNConfig;

View File

@@ -65,7 +65,7 @@ const AccessFormProxmoxVEConfig = ({ form: formInst, formName, disabled, initial
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.proxmoxve_api_token_secret.tooltip") }}></span>}
>
<Input.Password autoComplete="new-password" placeholder={t("access.form.proxmoxve_api_token_secret.placeholder")} />
<Input.Password allowClear autoComplete="new-password" placeholder={t("access.form.proxmoxve_api_token_secret.placeholder")} />
</Form.Item>
<Form.Item name="allowInsecureConnections" label={t("access.form.proxmoxve_allow_insecure_conns.label")} rules={[formRule]}>

View File

@@ -0,0 +1,82 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type AccessConfigForRatPanel } from "@/domain/access";
type AccessFormRatPanelConfigFieldValues = Nullish<AccessConfigForRatPanel>;
export type AccessFormRatPanelConfigProps = {
form: FormInstance;
formName: string;
disabled?: boolean;
initialValues?: AccessFormRatPanelConfigFieldValues;
onValuesChange?: (values: AccessFormRatPanelConfigFieldValues) => void;
};
const initFormModel = (): AccessFormRatPanelConfigFieldValues => {
return {
apiUrl: "http://<your-host-addr>:8888/",
accessTokenId: 1,
accessToken: "",
};
};
const AccessFormRatPanelConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormRatPanelConfigProps) => {
const { t } = useTranslation();
const formSchema = z.object({
apiUrl: z.string().url(t("common.errmsg.url_invalid")),
accessTokenId: z.preprocess((v) => Number(v), z.number().positive(t("access.form.ratpanel_access_token_id.placeholder"))),
accessToken: z.string().nonempty(t("access.form.ratpanel_access_token.placeholder")).trim(),
allowInsecureConnections: z.boolean().nullish(),
});
const formRule = createSchemaFieldRule(formSchema);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
};
return (
<Form
form={formInst}
disabled={disabled}
initialValues={initialValues ?? initFormModel()}
layout="vertical"
name={formName}
onValuesChange={handleFormChange}
>
<Form.Item name="apiUrl" label={t("access.form.ratpanel_api_url.label")} rules={[formRule]}>
<Input placeholder={t("access.form.ratpanel_api_url.placeholder")} />
</Form.Item>
<Form.Item
name="accessTokenId"
label={t("access.form.ratpanel_access_token_id.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.ratpanel_access_token_id.tooltip") }}></span>}
>
<Input type="number" placeholder={t("access.form.ratpanel_access_token_id.placeholder")} />
</Form.Item>
<Form.Item
name="accessToken"
label={t("access.form.ratpanel_access_token.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.ratpanel_access_token.tooltip") }}></span>}
>
<Input.Password autoComplete="new-password" placeholder={t("access.form.ratpanel_access_token.placeholder")} />
</Form.Item>
<Form.Item name="allowInsecureConnections" label={t("access.form.ratpanel_allow_insecure_conns.label")} rules={[formRule]}>
<Switch
checkedChildren={t("access.form.ratpanel_allow_insecure_conns.switch.on")}
unCheckedChildren={t("access.form.ratpanel_allow_insecure_conns.switch.off")}
/>
</Form.Item>
</Form>
);
};
export default AccessFormRatPanelConfig;

View File

@@ -81,7 +81,7 @@ const AccessFormUCloudConfig = ({ form: formInst, formName, disabled, initialVal
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.ucloud_project_id.tooltip") }}></span>}
>
<Input autoComplete="new-password" placeholder={t("access.form.ucloud_project_id.placeholder")} />
<Input allowClear autoComplete="new-password" placeholder={t("access.form.ucloud_project_id.placeholder")} />
</Form.Item>
</Form>
);

View File

@@ -66,7 +66,7 @@ const AccessFormVercelConfig = ({ form: formInst, formName, disabled, initialVal
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.vercel_team_id.tooltip") }}></span>}
>
<Input placeholder={t("access.form.vercel_team_id.placeholder")} />
<Input allowClear placeholder={t("access.form.vercel_team_id.placeholder")} />
</Form.Item>
</Form>
);

View File

@@ -67,7 +67,6 @@ const AccessFormWebhookConfig = ({ form: formInst, formName, disabled, initialVa
}
return true;
}, t("access.form.webhook_headers.errmsg.invalid")),
allowInsecureConnections: z.boolean().nullish(),
defaultDataForDeployment: z
.string()
.nullish()
@@ -96,11 +95,12 @@ const AccessFormWebhookConfig = ({ form: formInst, formName, disabled, initialVa
return false;
}
}, t("access.form.webhook_default_data.errmsg.json_invalid")),
allowInsecureConnections: z.boolean().nullish(),
});
const formRule = createSchemaFieldRule(formSchema);
const handleWebhookHeadersBlur = (e: React.FocusEvent<HTMLTextAreaElement>) => {
let value = e.target.value;
const handleWebhookHeadersBlur = () => {
let value = formInst.getFieldValue("headers");
value = value.trim();
value = value.replace(/(?<!\r)\n/g, "\r\n");
formInst.setFieldValue("headers", value);
@@ -279,7 +279,13 @@ const AccessFormWebhookConfig = ({ form: formInst, formName, disabled, initialVa
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.webhook_headers.tooltip") }}></span>}
>
<Input.TextArea autoSize={{ minRows: 3, maxRows: 10 }} placeholder={t("access.form.webhook_headers.placeholder")} onBlur={handleWebhookHeadersBlur} />
<CodeInput
height="auto"
minHeight="64px"
maxHeight="256px"
placeholder={t("access.form.webhook_headers.placeholder")}
onBlur={handleWebhookHeadersBlur}
/>
</Form.Item>
<Show when={!usage || usage === "deployment"}>

View File

@@ -42,7 +42,7 @@ const CertificateDetail = ({ data, ...props }: CertificateDetailProps) => {
</Form.Item>
<Form.Item label={t("certificate.props.issuer")}>
<Input value={data.issuer} variant="filled" placeholder="" />
<Input value={data.issuerOrg} variant="filled" placeholder="" />
</Form.Item>
<Form.Item label={t("certificate.props.validity")}>

View File

@@ -72,8 +72,10 @@ const DeploymentProviderPicker = ({ className, style, autoFocus, filter, placeho
DEPLOYMENT_CATEGORIES.LOADBALANCE,
DEPLOYMENT_CATEGORIES.FIREWALL,
DEPLOYMENT_CATEGORIES.AV,
DEPLOYMENT_CATEGORIES.APIGATEWAY,
DEPLOYMENT_CATEGORIES.SERVERLESS,
DEPLOYMENT_CATEGORIES.WEBSITE,
DEPLOYMENT_CATEGORIES.SSL,
DEPLOYMENT_CATEGORIES.NAS,
DEPLOYMENT_CATEGORIES.OTHER,
].map((key) => ({

View File

@@ -27,6 +27,7 @@ import DeployNodeConfigFormAliyunDCDNConfig from "./DeployNodeConfigFormAliyunDC
import DeployNodeConfigFormAliyunDDoSConfig from "./DeployNodeConfigFormAliyunDDoSConfig";
import DeployNodeConfigFormAliyunESAConfig from "./DeployNodeConfigFormAliyunESAConfig";
import DeployNodeConfigFormAliyunFCConfig from "./DeployNodeConfigFormAliyunFCConfig";
import DeployNodeConfigFormAliyunGAConfig from "./DeployNodeConfigFormAliyunGAConfig";
import DeployNodeConfigFormAliyunLiveConfig from "./DeployNodeConfigFormAliyunLiveConfig";
import DeployNodeConfigFormAliyunNLBConfig from "./DeployNodeConfigFormAliyunNLBConfig";
import DeployNodeConfigFormAliyunOSSConfig from "./DeployNodeConfigFormAliyunOSSConfig";
@@ -41,11 +42,13 @@ import DeployNodeConfigFormBaiduCloudCDNConfig from "./DeployNodeConfigFormBaidu
import DeployNodeConfigFormBaishanCDNConfig from "./DeployNodeConfigFormBaishanCDNConfig";
import DeployNodeConfigFormBaotaPanelConsoleConfig from "./DeployNodeConfigFormBaotaPanelConsoleConfig";
import DeployNodeConfigFormBaotaPanelSiteConfig from "./DeployNodeConfigFormBaotaPanelSiteConfig";
import DeployNodeConfigFormBaotaWAFSiteConfig from "./DeployNodeConfigFormBaotaWAFSiteConfig";
import DeployNodeConfigFormBunnyCDNConfig from "./DeployNodeConfigFormBunnyCDNConfig.tsx";
import DeployNodeConfigFormBytePlusCDNConfig from "./DeployNodeConfigFormBytePlusCDNConfig";
import DeployNodeConfigFormCdnflyConfig from "./DeployNodeConfigFormCdnflyConfig";
import DeployNodeConfigFormDogeCloudCDNConfig from "./DeployNodeConfigFormDogeCloudCDNConfig";
import DeployNodeConfigFormEdgioApplicationsConfig from "./DeployNodeConfigFormEdgioApplicationsConfig";
import DeployNodeConfigFormFlexCDNConfig from "./DeployNodeConfigFormFlexCDNConfig";
import DeployNodeConfigFormGcoreCDNConfig from "./DeployNodeConfigFormGcoreCDNConfig";
import DeployNodeConfigFormGoEdgeConfig from "./DeployNodeConfigFormGoEdgeConfig";
import DeployNodeConfigFormHuaweiCloudCDNConfig from "./DeployNodeConfigFormHuaweiCloudCDNConfig";
@@ -56,6 +59,7 @@ import DeployNodeConfigFormJDCloudCDNConfig from "./DeployNodeConfigFormJDCloudC
import DeployNodeConfigFormJDCloudLiveConfig from "./DeployNodeConfigFormJDCloudLiveConfig";
import DeployNodeConfigFormJDCloudVODConfig from "./DeployNodeConfigFormJDCloudVODConfig";
import DeployNodeConfigFormKubernetesSecretConfig from "./DeployNodeConfigFormKubernetesSecretConfig";
import DeployNodeConfigFormLeCDNConfig from "./DeployNodeConfigFormLeCDNConfig";
import DeployNodeConfigFormLocalConfig from "./DeployNodeConfigFormLocalConfig";
import DeployNodeConfigFormNetlifySiteConfig from "./DeployNodeConfigFormNetlifySiteConfig";
import DeployNodeConfigFormProxmoxVEConfig from "./DeployNodeConfigFormProxmoxVEConfig";
@@ -63,6 +67,7 @@ import DeployNodeConfigFormQiniuCDNConfig from "./DeployNodeConfigFormQiniuCDNCo
import DeployNodeConfigFormQiniuKodoConfig from "./DeployNodeConfigFormQiniuKodoConfig";
import DeployNodeConfigFormQiniuPiliConfig from "./DeployNodeConfigFormQiniuPiliConfig";
import DeployNodeConfigFormRainYunRCDNConfig from "./DeployNodeConfigFormRainYunRCDNConfig";
import DeployNodeConfigFormRatPanelSiteConfig from "./DeployNodeConfigFormRatPanelSiteConfig";
import DeployNodeConfigFormSafeLineConfig from "./DeployNodeConfigFormSafeLineConfig";
import DeployNodeConfigFormSSHConfig from "./DeployNodeConfigFormSSHConfig.tsx";
import DeployNodeConfigFormTencentCloudCDNConfig from "./DeployNodeConfigFormTencentCloudCDNConfig.tsx";
@@ -87,7 +92,9 @@ import DeployNodeConfigFormVolcEngineDCDNConfig from "./DeployNodeConfigFormVolc
import DeployNodeConfigFormVolcEngineImageXConfig from "./DeployNodeConfigFormVolcEngineImageXConfig.tsx";
import DeployNodeConfigFormVolcEngineLiveConfig from "./DeployNodeConfigFormVolcEngineLiveConfig.tsx";
import DeployNodeConfigFormVolcEngineTOSConfig from "./DeployNodeConfigFormVolcEngineTOSConfig.tsx";
import DeployNodeConfigFormWangsuCDNConfig from "./DeployNodeConfigFormWangsuCDNConfig.tsx";
import DeployNodeConfigFormWangsuCDNProConfig from "./DeployNodeConfigFormWangsuCDNProConfig.tsx";
import DeployNodeConfigFormWangsuCertificateConfig from "./DeployNodeConfigFormWangsuCertificateConfig.tsx";
import DeployNodeConfigFormWebhookConfig from "./DeployNodeConfigFormWebhookConfig.tsx";
type DeployNodeConfigFormFieldValues = Partial<WorkflowNodeConfigForDeploy>;
@@ -201,6 +208,8 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
return <DeployNodeConfigFormAliyunESAConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.ALIYUN_FC:
return <DeployNodeConfigFormAliyunFCConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.ALIYUN_GA:
return <DeployNodeConfigFormAliyunGAConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.ALIYUN_LIVE:
return <DeployNodeConfigFormAliyunLiveConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.ALIYUN_NLB:
@@ -229,6 +238,8 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
return <DeployNodeConfigFormBaotaPanelConsoleConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.BAOTAPANEL_SITE:
return <DeployNodeConfigFormBaotaPanelSiteConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.BAOTAWAF_SITE:
return <DeployNodeConfigFormBaotaWAFSiteConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.BUNNY_CDN:
return <DeployNodeConfigFormBunnyCDNConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.BYTEPLUS_CDN:
@@ -239,6 +250,8 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
return <DeployNodeConfigFormDogeCloudCDNConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.EDGIO_APPLICATIONS:
return <DeployNodeConfigFormEdgioApplicationsConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.FLEXCDN:
return <DeployNodeConfigFormFlexCDNConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.GCORE_CDN:
return <DeployNodeConfigFormGcoreCDNConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.GOEDGE:
@@ -259,6 +272,8 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
return <DeployNodeConfigFormJDCloudVODConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.KUBERNETES_SECRET:
return <DeployNodeConfigFormKubernetesSecretConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.LECDN:
return <DeployNodeConfigFormLeCDNConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.LOCAL:
return <DeployNodeConfigFormLocalConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.NETLIFY_SITE:
@@ -273,6 +288,8 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
return <DeployNodeConfigFormQiniuPiliConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.RAINYUN_RCDN:
return <DeployNodeConfigFormRainYunRCDNConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.RATPANEL_SITE:
return <DeployNodeConfigFormRatPanelSiteConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.SAFELINE:
return <DeployNodeConfigFormSafeLineConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.SSH:
@@ -321,8 +338,12 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
return <DeployNodeConfigFormVolcEngineLiveConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.VOLCENGINE_TOS:
return <DeployNodeConfigFormVolcEngineTOSConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.WANGSU_CDN:
return <DeployNodeConfigFormWangsuCDNConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.WANGSU_CDNPRO:
return <DeployNodeConfigFormWangsuCDNProConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.WANGSU_CERTIFICATE:
return <DeployNodeConfigFormWangsuCertificateConfig {...nestedFormProps} />;
case DEPLOYMENT_PROVIDERS.WEBHOOK:
return <DeployNodeConfigFormWebhookConfig {...nestedFormProps} />;
}

View File

@@ -28,7 +28,7 @@ const DeployNodeConfigFormAWSACMConfig = ({ form: formInst, formName, disabled,
.string({ message: t("workflow_node.deploy.form.aws_acm_region.placeholder") })
.nonempty(t("workflow_node.deploy.form.aws_acm_region.placeholder"))
.trim(),
certificateArn: z.string({ message: t("workflow_node.deploy.form.aws_acm_certificate_arn.placeholder") }).nullish(),
certificateArn: z.string().nullish(),
});
const formRule = createSchemaFieldRule(formSchema);
@@ -60,7 +60,7 @@ const DeployNodeConfigFormAWSACMConfig = ({ form: formInst, formName, disabled,
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aws_acm_certificate_arn.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.aws_acm_certificate_arn.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.aws_acm_certificate_arn.placeholder")} />
</Form.Item>
</Form>
);

View File

@@ -132,7 +132,7 @@ const DeployNodeConfigFormAliyunALBConfig = ({
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_alb_snidomain.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.aliyun_alb_snidomain.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.aliyun_alb_snidomain.placeholder")} />
</Form.Item>
</Show>
</Form>

View File

@@ -132,7 +132,7 @@ const DeployNodeConfigFormAliyunCLBConfig = ({
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_clb_snidomain.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.aliyun_clb_snidomain.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.aliyun_clb_snidomain.placeholder")} />
</Form.Item>
</Show>
</Form>

View File

@@ -0,0 +1,118 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Select } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import Show from "@/components/Show";
import { validDomainName } from "@/utils/validators";
type DeployNodeConfigFormAliyunGAConfigFieldValues = Nullish<{
resourceType: string;
acceleratorId?: string;
listenerId?: string;
domain?: string;
}>;
export type DeployNodeConfigFormAliyunGAConfigProps = {
form: FormInstance;
formName: string;
disabled?: boolean;
initialValues?: DeployNodeConfigFormAliyunGAConfigFieldValues;
onValuesChange?: (values: DeployNodeConfigFormAliyunGAConfigFieldValues) => void;
};
const RESOURCE_TYPE_ACCELERATOR = "accelerator" as const;
const RESOURCE_TYPE_LISTENER = "listener" as const;
const initFormModel = (): DeployNodeConfigFormAliyunGAConfigFieldValues => {
return {};
};
const DeployNodeConfigFormAliyunGAConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: DeployNodeConfigFormAliyunGAConfigProps) => {
const { t } = useTranslation();
const formSchema = z.object({
resourceType: z.union([z.literal(RESOURCE_TYPE_ACCELERATOR), z.literal(RESOURCE_TYPE_LISTENER)], {
message: t("workflow_node.deploy.form.aliyun_ga_resource_type.placeholder"),
}),
acceleratorId: z
.string()
.max(64, t("common.errmsg.string_max", { max: 64 }))
.trim(),
listenerId: z
.string()
.max(64, t("common.errmsg.string_max", { max: 64 }))
.trim()
.nullish()
.refine((v) => fieldResourceType !== RESOURCE_TYPE_LISTENER || !!v?.trim(), t("workflow_node.deploy.form.aliyun_ga_listener_id.placeholder")),
domain: z
.string()
.nullish()
.refine((v) => {
if (![RESOURCE_TYPE_ACCELERATOR, RESOURCE_TYPE_LISTENER].includes(fieldResourceType)) return true;
return !v || validDomainName(v!);
}, t("common.errmsg.domain_invalid")),
});
const formRule = createSchemaFieldRule(formSchema);
const fieldResourceType = Form.useWatch("resourceType", formInst);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
};
return (
<Form
form={formInst}
disabled={disabled}
initialValues={initialValues ?? initFormModel()}
layout="vertical"
name={formName}
onValuesChange={handleFormChange}
>
<Form.Item name="resourceType" label={t("workflow_node.deploy.form.aliyun_ga_resource_type.label")} rules={[formRule]}>
<Select placeholder={t("workflow_node.deploy.form.aliyun_ga_resource_type.placeholder")}>
<Select.Option key={RESOURCE_TYPE_ACCELERATOR} value={RESOURCE_TYPE_ACCELERATOR}>
{t("workflow_node.deploy.form.aliyun_ga_resource_type.option.accelerator.label")}
</Select.Option>
<Select.Option key={RESOURCE_TYPE_LISTENER} value={RESOURCE_TYPE_LISTENER}>
{t("workflow_node.deploy.form.aliyun_ga_resource_type.option.listener.label")}
</Select.Option>
</Select>
</Form.Item>
<Form.Item
name="acceleratorId"
label={t("workflow_node.deploy.form.aliyun_ga_accelerator_id.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_ga_accelerator_id.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.aliyun_ga_accelerator_id.placeholder")} />
</Form.Item>
<Show when={fieldResourceType === RESOURCE_TYPE_LISTENER}>
<Form.Item
name="listenerId"
label={t("workflow_node.deploy.form.aliyun_ga_listener_id.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_ga_listener_id.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.aliyun_ga_listener_id.placeholder")} />
</Form.Item>
</Show>
<Show when={fieldResourceType === RESOURCE_TYPE_ACCELERATOR || fieldResourceType === RESOURCE_TYPE_LISTENER}>
<Form.Item
name="domain"
label={t("workflow_node.deploy.form.aliyun_ga_snidomain.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_ga_snidomain.tooltip") }}></span>}
>
<Input allowClear placeholder={t("workflow_node.deploy.form.aliyun_ga_snidomain.placeholder")} />
</Form.Item>
</Show>
</Form>
);
};
export default DeployNodeConfigFormAliyunGAConfig;

View File

@@ -102,7 +102,7 @@ const DeployNodeConfigFormAliyunWAFConfig = ({
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_waf_domain.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.aliyun_waf_domain.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.aliyun_waf_domain.placeholder")} />
</Form.Item>
</Form>
);

View File

@@ -35,7 +35,7 @@ const DeployNodeConfigFormAzureKeyVaultConfig = ({
.nonempty(t("workflow_node.deploy.form.azure_keyvault_name.placeholder"))
.trim(),
certificateName: z
.string({ message: t("workflow_node.deploy.form.azure_keyvault_certificate_name.placeholder") })
.string()
.nullish()
.refine((v) => {
if (!v) return true;

View File

@@ -135,7 +135,7 @@ const DeployNodeConfigFormBaiduCloudAppBLBConfig = ({
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.baiducloud_appblb_snidomain.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.baiducloud_appblb_snidomain.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.baiducloud_appblb_snidomain.placeholder")} />
</Form.Item>
</Show>
</Form>

View File

@@ -135,7 +135,7 @@ const DeployNodeConfigFormBaiduCloudBLBConfig = ({
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.baiducloud_blb_snidomain.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.baiducloud_blb_snidomain.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.baiducloud_blb_snidomain.placeholder")} />
</Form.Item>
</Show>
</Form>

View File

@@ -73,7 +73,7 @@ const DeployNodeConfigFormBaishanCDNConfig = ({
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.baishan_cdn_certificate_id.tooltip") }}></span>}
>
<Input type="number" placeholder={t("workflow_node.deploy.form.baishan_cdn_certificate_id.placeholder")} />
<Input allowClear type="number" placeholder={t("workflow_node.deploy.form.baishan_cdn_certificate_id.placeholder")} />
</Form.Item>
</Form>
);

View File

@@ -0,0 +1,78 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, InputNumber } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { validPortNumber } from "@/utils/validators";
type DeployNodeConfigFormBaotaWAFSiteConfigFieldValues = Nullish<{
siteName: string;
sitePort: number;
}>;
export type DeployNodeConfigFormBaotaWAFSiteConfigProps = {
form: FormInstance;
formName: string;
disabled?: boolean;
initialValues?: DeployNodeConfigFormBaotaWAFSiteConfigFieldValues;
onValuesChange?: (values: DeployNodeConfigFormBaotaWAFSiteConfigFieldValues) => void;
};
const initFormModel = (): DeployNodeConfigFormBaotaWAFSiteConfigFieldValues => {
return {
siteName: "",
sitePort: 443,
};
};
const DeployNodeConfigFormBaotaWAFSiteConfig = ({
form: formInst,
formName,
disabled,
initialValues,
onValuesChange,
}: DeployNodeConfigFormBaotaWAFSiteConfigProps) => {
const { t } = useTranslation();
const formSchema = z.object({
siteName: z.string().nonempty(t("workflow_node.deploy.form.baotawaf_site_name.placeholder")).trim(),
sitePort: z.preprocess(
(v) => Number(v),
z
.number()
.int(t("workflow_node.deploy.form.baotawaf_site_port.placeholder"))
.refine((v) => validPortNumber(v), t("common.errmsg.port_invalid"))
),
});
const formRule = createSchemaFieldRule(formSchema);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
};
return (
<Form
form={formInst}
disabled={disabled}
initialValues={initialValues ?? initFormModel()}
layout="vertical"
name={formName}
onValuesChange={handleFormChange}
>
<Form.Item
name="siteName"
label={t("workflow_node.deploy.form.baotawaf_site_name.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.baotawaf_site_name.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.baotawaf_site_name.placeholder")} />
</Form.Item>
<Form.Item name="sitePort" label={t("workflow_node.deploy.form.baotawaf_site_port.label")} rules={[formRule]}>
<InputNumber className="w-full" placeholder={t("access.form.ssh_port.placeholder")} min={1} max={65535} />
</Form.Item>
</Form>
);
};
export default DeployNodeConfigFormBaotaWAFSiteConfig;

View File

@@ -79,13 +79,23 @@ const DeployNodeConfigFormCdnflyConfig = ({ form: formInst, formName, disabled,
</Form.Item>
<Show when={fieldResourceType === RESOURCE_TYPE_SITE}>
<Form.Item name="siteId" label={t("workflow_node.deploy.form.cdnfly_site_id.label")} rules={[formRule]}>
<Form.Item
name="siteId"
label={t("workflow_node.deploy.form.cdnfly_site_id.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.cdnfly_site_id.tooltip") }}></span>}
>
<Input type="number" placeholder={t("workflow_node.deploy.form.cdnfly_site_id.placeholder")} />
</Form.Item>
</Show>
<Show when={fieldResourceType === RESOURCE_TYPE_CERTIFICATE}>
<Form.Item name="certificateId" label={t("workflow_node.deploy.form.cdnfly_certificate_id.label")} rules={[formRule]}>
<Form.Item
name="certificateId"
label={t("workflow_node.deploy.form.cdnfly_certificate_id.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.cdnfly_certificate_id.tooltip") }}></span>}
>
<Input type="number" placeholder={t("workflow_node.deploy.form.cdnfly_certificate_id.placeholder")} />
</Form.Item>
</Show>

View File

@@ -0,0 +1,84 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Select } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import Show from "@/components/Show";
type DeployNodeConfigFormFlexCDNConfigFieldValues = Nullish<{
resourceType: string;
certificateId?: string | number;
}>;
export type DeployNodeConfigFormFlexCDNConfigProps = {
form: FormInstance;
formName: string;
disabled?: boolean;
initialValues?: DeployNodeConfigFormFlexCDNConfigFieldValues;
onValuesChange?: (values: DeployNodeConfigFormFlexCDNConfigFieldValues) => void;
};
const RESOURCE_TYPE_CERTIFICATE = "certificate" as const;
const initFormModel = (): DeployNodeConfigFormFlexCDNConfigFieldValues => {
return {
resourceType: RESOURCE_TYPE_CERTIFICATE,
certificateId: "",
};
};
const DeployNodeConfigFormFlexCDNConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: DeployNodeConfigFormFlexCDNConfigProps) => {
const { t } = useTranslation();
const formSchema = z.object({
resourceType: z.literal(RESOURCE_TYPE_CERTIFICATE, {
message: t("workflow_node.deploy.form.flexcdn_resource_type.placeholder"),
}),
certificateId: z
.union([z.string(), z.number().int()])
.nullish()
.refine((v) => {
if (fieldResourceType !== RESOURCE_TYPE_CERTIFICATE) return true;
return /^\d+$/.test(v + "") && +v! > 0;
}, t("workflow_node.deploy.form.flexcdn_certificate_id.placeholder")),
});
const formRule = createSchemaFieldRule(formSchema);
const fieldResourceType = Form.useWatch("resourceType", formInst);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
};
return (
<Form
form={formInst}
disabled={disabled}
initialValues={initialValues ?? initFormModel()}
layout="vertical"
name={formName}
onValuesChange={handleFormChange}
>
<Form.Item name="resourceType" label={t("workflow_node.deploy.form.flexcdn_resource_type.label")} rules={[formRule]}>
<Select placeholder={t("workflow_node.deploy.form.flexcdn_resource_type.placeholder")}>
<Select.Option key={RESOURCE_TYPE_CERTIFICATE} value={RESOURCE_TYPE_CERTIFICATE}>
{t("workflow_node.deploy.form.flexcdn_resource_type.option.certificate.label")}
</Select.Option>
</Select>
</Form.Item>
<Show when={fieldResourceType === RESOURCE_TYPE_CERTIFICATE}>
<Form.Item
name="certificateId"
label={t("workflow_node.deploy.form.flexcdn_certificate_id.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.flexcdn_certificate_id.tooltip") }}></span>}
>
<Input type="number" placeholder={t("workflow_node.deploy.form.flexcdn_certificate_id.placeholder")} />
</Form.Item>
</Show>
</Form>
);
};
export default DeployNodeConfigFormFlexCDNConfig;

View File

@@ -67,7 +67,7 @@ const DeployNodeConfigFormGcoreCDNConfig = ({ form: formInst, formName, disabled
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.gcore_cdn_certificate_id.tooltip") }}></span>}
>
<Input type="number" placeholder={t("workflow_node.deploy.form.gcore_cdn_certificate_id.placeholder")} />
<Input allowClear type="number" placeholder={t("workflow_node.deploy.form.gcore_cdn_certificate_id.placeholder")} />
</Form.Item>
</Form>
);

View File

@@ -68,7 +68,12 @@ const DeployNodeConfigFormGoEdgeConfig = ({ form: formInst, formName, disabled,
</Form.Item>
<Show when={fieldResourceType === RESOURCE_TYPE_CERTIFICATE}>
<Form.Item name="certificateId" label={t("workflow_node.deploy.form.goedge_certificate_id.label")} rules={[formRule]}>
<Form.Item
name="certificateId"
label={t("workflow_node.deploy.form.goedge_certificate_id.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.goedge_certificate_id.tooltip") }}></span>}
>
<Input type="number" placeholder={t("workflow_node.deploy.form.goedge_certificate_id.placeholder")} />
</Form.Item>
</Show>

View File

@@ -132,7 +132,7 @@ const DeployNodeConfigFormJDCloudALBConfig = ({
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.jdcloud_alb_snidomain.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.jdcloud_alb_snidomain.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.jdcloud_alb_snidomain.placeholder")} />
</Form.Item>
</Show>
</Form>

View File

@@ -0,0 +1,103 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Select } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import Show from "@/components/Show";
type DeployNodeConfigFormLeCDNConfigFieldValues = Nullish<{
resourceType: string;
certificateId?: string | number;
clientId?: string | number;
}>;
export type DeployNodeConfigFormLeCDNConfigProps = {
form: FormInstance;
formName: string;
disabled?: boolean;
initialValues?: DeployNodeConfigFormLeCDNConfigFieldValues;
onValuesChange?: (values: DeployNodeConfigFormLeCDNConfigFieldValues) => void;
};
const RESOURCE_TYPE_CERTIFICATE = "certificate" as const;
const initFormModel = (): DeployNodeConfigFormLeCDNConfigFieldValues => {
return {
resourceType: RESOURCE_TYPE_CERTIFICATE,
certificateId: "",
clientId: "",
};
};
const DeployNodeConfigFormLeCDNConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: DeployNodeConfigFormLeCDNConfigProps) => {
const { t } = useTranslation();
const formSchema = z.object({
resourceType: z.literal(RESOURCE_TYPE_CERTIFICATE, {
message: t("workflow_node.deploy.form.lecdn_resource_type.placeholder"),
}),
certificateId: z
.union([z.string(), z.number().int()])
.nullish()
.refine((v) => {
if (fieldResourceType !== RESOURCE_TYPE_CERTIFICATE) return true;
return /^\d+$/.test(v + "") && +v! > 0;
}, t("workflow_node.deploy.form.lecdn_certificate_id.placeholder")),
clientId: z
.union([z.string(), z.number().int()])
.nullish()
.refine((v) => {
if (fieldResourceType !== RESOURCE_TYPE_CERTIFICATE) return true;
if (v == null || v === "") return true;
return /^\d+$/.test(v + "") && +v! > 0;
}, t("workflow_node.deploy.form.lecdn_client_id.placeholder")),
});
const formRule = createSchemaFieldRule(formSchema);
const fieldResourceType = Form.useWatch("resourceType", formInst);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
};
return (
<Form
form={formInst}
disabled={disabled}
initialValues={initialValues ?? initFormModel()}
layout="vertical"
name={formName}
onValuesChange={handleFormChange}
>
<Form.Item name="resourceType" label={t("workflow_node.deploy.form.lecdn_resource_type.label")} rules={[formRule]}>
<Select placeholder={t("workflow_node.deploy.form.lecdn_resource_type.placeholder")}>
<Select.Option key={RESOURCE_TYPE_CERTIFICATE} value={RESOURCE_TYPE_CERTIFICATE}>
{t("workflow_node.deploy.form.lecdn_resource_type.option.certificate.label")}
</Select.Option>
</Select>
</Form.Item>
<Show when={fieldResourceType === RESOURCE_TYPE_CERTIFICATE}>
<Form.Item
name="certificateId"
label={t("workflow_node.deploy.form.lecdn_certificate_id.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.lecdn_certificate_id.tooltip") }}></span>}
>
<Input type="number" placeholder={t("workflow_node.deploy.form.lecdn_certificate_id.placeholder")} />
</Form.Item>
<Form.Item
name="clientId"
label={t("workflow_node.deploy.form.lecdn_client_id.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.lecdn_client_id.tooltip") }}></span>}
>
<Input type="number" allowClear placeholder={t("workflow_node.deploy.form.lecdn_client_id.placeholder")} />
</Form.Item>
</Show>
</Form>
);
};
export default DeployNodeConfigFormLeCDNConfig;

View File

@@ -351,7 +351,7 @@ const DeployNodeConfigFormLocalConfig = ({ form: formInst, formName, disabled, i
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.local_servercert_path.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.local_servercert_path.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.local_servercert_path.placeholder")} />
</Form.Item>
<Form.Item
@@ -360,7 +360,7 @@ const DeployNodeConfigFormLocalConfig = ({ form: formInst, formName, disabled, i
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.local_intermediacert_path.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.local_intermediacert_path.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.local_intermediacert_path.placeholder")} />
</Form.Item>
</Show>

View File

@@ -0,0 +1,63 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
type DeployNodeConfigFormRatPanelSiteConfigFieldValues = Nullish<{
siteName: string;
}>;
export type DeployNodeConfigFormRatPanelSiteConfigProps = {
form: FormInstance;
formName: string;
disabled?: boolean;
initialValues?: DeployNodeConfigFormRatPanelSiteConfigFieldValues;
onValuesChange?: (values: DeployNodeConfigFormRatPanelSiteConfigFieldValues) => void;
};
const initFormModel = (): DeployNodeConfigFormRatPanelSiteConfigFieldValues => {
return {
siteName: "",
};
};
const DeployNodeConfigFormRatPanelSiteConfig = ({
form: formInst,
formName,
disabled,
initialValues,
onValuesChange,
}: DeployNodeConfigFormRatPanelSiteConfigProps) => {
const { t } = useTranslation();
const formSchema = z.object({
siteName: z.string().nonempty(t("workflow_node.deploy.form.ratpanel_site_name.placeholder")),
});
const formRule = createSchemaFieldRule(formSchema);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
};
return (
<Form
form={formInst}
disabled={disabled}
initialValues={initialValues ?? initFormModel()}
layout="vertical"
name={formName}
onValuesChange={handleFormChange}
>
<Form.Item
name="siteName"
label={t("workflow_node.deploy.form.ratpanel_site_name.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.ratpanel_site_name.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.ratpanel_site_name.placeholder")} />
</Form.Item>
</Form>
);
};
export default DeployNodeConfigFormRatPanelSiteConfig;

View File

@@ -363,7 +363,7 @@ const DeployNodeConfigFormSSHConfig = ({ form: formInst, formName, disabled, ini
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.ssh_servercert_path.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.ssh_servercert_path.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.ssh_servercert_path.placeholder")} />
</Form.Item>
<Form.Item
@@ -372,7 +372,7 @@ const DeployNodeConfigFormSSHConfig = ({ form: formInst, formName, disabled, ini
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.ssh_intermediacert_path.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.ssh_intermediacert_path.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.ssh_intermediacert_path.placeholder")} />
</Form.Item>
</Show>

View File

@@ -68,7 +68,12 @@ const DeployNodeConfigFormSafeLineConfig = ({ form: formInst, formName, disabled
</Form.Item>
<Show when={fieldResourceType === RESOURCE_TYPE_CERTIFICATE}>
<Form.Item name="certificateId" label={t("workflow_node.deploy.form.safeline_certificate_id.label")} rules={[formRule]}>
<Form.Item
name="certificateId"
label={t("workflow_node.deploy.form.safeline_certificate_id.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.safeline_certificate_id.tooltip") }}></span>}
>
<Input type="number" placeholder={t("workflow_node.deploy.form.safeline_certificate_id.placeholder")} />
</Form.Item>
</Show>

View File

@@ -144,7 +144,7 @@ const DeployNodeConfigFormTencentCloudCLBConfig = ({
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_clb_snidomain.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.tencentcloud_clb_snidomain.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.tencentcloud_clb_snidomain.placeholder")} />
</Form.Item>
</Show>

View File

@@ -140,7 +140,7 @@ const DeployNodeConfigFormVolcEngineALBConfig = ({
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.volcengine_alb_snidomain.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.volcengine_alb_snidomain.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.volcengine_alb_snidomain.placeholder")} />
</Form.Item>
</Show>
</Form>

View File

@@ -0,0 +1,146 @@
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 { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import ModalForm from "@/components/ModalForm";
import MultipleInput from "@/components/MultipleInput";
import { useAntdForm } from "@/hooks";
import { validDomainName } from "@/utils/validators";
type DeployNodeConfigFormWangsuCDNConfigFieldValues = Nullish<{
domains: string;
}>;
export type DeployNodeConfigFormWangsuCDNConfigProps = {
form: FormInstance;
formName: string;
disabled?: boolean;
initialValues?: DeployNodeConfigFormWangsuCDNConfigFieldValues;
onValuesChange?: (values: DeployNodeConfigFormWangsuCDNConfigFieldValues) => void;
};
const MULTIPLE_INPUT_DELIMITER = ";";
const initFormModel = (): DeployNodeConfigFormWangsuCDNConfigFieldValues => {
return {
domains: "",
};
};
const DeployNodeConfigFormWangsuCDNConfig = ({
form: formInst,
formName,
disabled,
initialValues,
onValuesChange,
}: DeployNodeConfigFormWangsuCDNConfigProps) => {
const { t } = useTranslation();
const formSchema = z.object({
domains: z
.string()
.nullish()
.refine((v) => {
if (!v) return false;
return String(v)
.split(MULTIPLE_INPUT_DELIMITER)
.every((e) => validDomainName(e));
}, t("workflow_node.deploy.form.wangsu_cdn_domains.placeholder")),
});
const formRule = createSchemaFieldRule(formSchema);
const fieldDomains = Form.useWatch<string>("domains", formInst);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
};
return (
<Form
form={formInst}
disabled={disabled}
initialValues={initialValues ?? initFormModel()}
layout="vertical"
name={formName}
onValuesChange={handleFormChange}
>
<Form.Item
label={t("workflow_node.deploy.form.wangsu_cdn_domains.label")}
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>
</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;

View File

@@ -5,37 +5,37 @@ import { z } from "zod";
import { validDomainName } from "@/utils/validators";
type DeployNodeConfigFormBaishanCDNConfigFieldValues = Nullish<{
type DeployNodeConfigFormWangsuCDNProConfigFieldValues = Nullish<{
environment: string;
domain: string;
certificateId?: string;
webhookId?: string;
}>;
export type DeployNodeConfigFormBaishanCDNConfigProps = {
export type DeployNodeConfigFormWangsuCDNProConfigProps = {
form: FormInstance;
formName: string;
disabled?: boolean;
initialValues?: DeployNodeConfigFormBaishanCDNConfigFieldValues;
onValuesChange?: (values: DeployNodeConfigFormBaishanCDNConfigFieldValues) => void;
initialValues?: DeployNodeConfigFormWangsuCDNProConfigFieldValues;
onValuesChange?: (values: DeployNodeConfigFormWangsuCDNProConfigFieldValues) => void;
};
const ENVIRONMENT_PRODUCTION = "production" as const;
const ENVIRONMENT_STAGING = "stating" as const;
const initFormModel = (): DeployNodeConfigFormBaishanCDNConfigFieldValues => {
const initFormModel = (): DeployNodeConfigFormWangsuCDNProConfigFieldValues => {
return {
environment: ENVIRONMENT_PRODUCTION,
};
};
const DeployNodeConfigFormBaishanCDNConfig = ({
const DeployNodeConfigFormWangsuCDNProConfig = ({
form: formInst,
formName,
disabled,
initialValues,
onValuesChange,
}: DeployNodeConfigFormBaishanCDNConfigProps) => {
}: DeployNodeConfigFormWangsuCDNProConfigProps) => {
const { t } = useTranslation();
const formSchema = z.object({
@@ -89,7 +89,7 @@ const DeployNodeConfigFormBaishanCDNConfig = ({
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.wangsu_cdnpro_certificate_id.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.wangsu_cdnpro_certificate_id.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.wangsu_cdnpro_certificate_id.placeholder")} />
</Form.Item>
<Form.Item
@@ -98,10 +98,10 @@ const DeployNodeConfigFormBaishanCDNConfig = ({
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.wangsu_cdnpro_webhook_id.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.wangsu_cdnpro_webhook_id.placeholder")} />
<Input allowClear placeholder={t("workflow_node.deploy.form.wangsu_cdnpro_webhook_id.placeholder")} />
</Form.Item>
</Form>
);
};
export default DeployNodeConfigFormBaishanCDNConfig;
export default DeployNodeConfigFormWangsuCDNProConfig;

View File

@@ -0,0 +1,61 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
type DeployNodeConfigFormWangsuCertificateConfigFieldValues = Nullish<{
certificateId?: string;
}>;
export type DeployNodeConfigFormWangsuCertificateConfigProps = {
form: FormInstance;
formName: string;
disabled?: boolean;
initialValues?: DeployNodeConfigFormWangsuCertificateConfigFieldValues;
onValuesChange?: (values: DeployNodeConfigFormWangsuCertificateConfigFieldValues) => void;
};
const initFormModel = (): DeployNodeConfigFormWangsuCertificateConfigFieldValues => {
return {};
};
const DeployNodeConfigFormWangsuCertificateConfig = ({
form: formInst,
formName,
disabled,
initialValues,
onValuesChange,
}: DeployNodeConfigFormWangsuCertificateConfigProps) => {
const { t } = useTranslation();
const formSchema = z.object({
certificateId: z.string().nullish(),
});
const formRule = createSchemaFieldRule(formSchema);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
};
return (
<Form
form={formInst}
disabled={disabled}
initialValues={initialValues ?? initFormModel()}
layout="vertical"
name={formName}
onValuesChange={handleFormChange}
>
<Form.Item
name="certificateId"
label={t("workflow_node.deploy.form.wangsu_certificate_id.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.wangsu_certificate_id.tooltip") }}></span>}
>
<Input allowClear placeholder={t("workflow_node.deploy.form.wangsu_certificate_id.placeholder")} />
</Form.Item>
</Form>
);
};
export default DeployNodeConfigFormWangsuCertificateConfig;